PageSourceSearch

https://www.openpolicyagent.org/assets/js/6432e603.8efac03e.js

js openpolicyagent.org collected 2026-09-24 08:30:56 UTC 6,761 bytes, 1 lines download raw bytes

1"use strict";(self.webpackChunkopa_website=self.webpackChunkopa_website||[]).push([[25392],{28453:(e,r,t)=>{t.d(r,{R:()=>i,x:()=>a});var n=t(96540);const o={},s=n.createContext(o);function i(e){const r=n.useContext(s);return n.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function a(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),n.createElement(s.Provider,{value:r},e.children)}},29129:(e,r,t)=>{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>a,default:()=>d,frontMatter:()=>i,metadata:()=>n,toc:()=>h});const n=JSON.parse('{"id":"errors/rego-type-error/match-error","title":"rego_type_error: match error","description":"As the category suggests, this error is emitted by the type checker during the compilation stage. This error","source":"@site/docs/errors/rego-type-error/match-error.md","sourceDirName":"errors/rego-type-error","slug":"/errors/rego-type-error/match-error","permalink":"/docs/errors/rego-type-error/match-error","draft":false,"unlisted":false,"tags":[],"version":"current","frontMatter":{"sidebar_label":"match error","image":"/img/opa-errors.png"},"sidebar":"docsSidebar","previous":{"title":"function name has arity n, got m argument(s)","permalink":"/docs/errors/rego-type-error/function-has-arity-got-argument"},"next":{"title":"multiple default rules {name} found","permalink":"/docs/errors/rego-type-error/multiple-default-rules-name-found"}}');var o=t(74848),s=t(28453);const i={sidebar_label:"match error",image:"/img/opa-errors.png"},a="rego_type_error: match error",c={},h=[{value:"Examples",id:"examples",level:2},{value:"How To Fix It",id:"how-to-fix-it",level:2}];function l(e){const r={a:"a",code:"code",em:"em",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,s.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(r.header,{children:(0,o.jsxs)(r.h1,{id:"rego_type_error-match-error",children:[(0,o.jsx)(r.code,{children:"rego_type_error"}),": match error"]})}),"\n",(0,o.jsxs)(r.p,{children:["As the category suggests, this error is emitted by the ",(0,o.jsx)(r.em,{children:"type checker"})," during the compilation stage. This error\nis commonly triggered by comparing two values of different types, like a string and an integer (",(0,o.jsx)(r.code,{children:'"1" == 1'}),"). In order\nfor the error to be reported, the compiler must be able to determine the types involved in the expression."]}),"\n",(0,o.jsxs)(r.p,{children:["This may sound obvious, but remember that some values and references aren't known until evaluation time. Comparing\nsomething to e.g. a value from ",(0,o.jsx)(r.code,{children:"input"})," will therefore not be reported by the type checker (unless the type checker\n",(0,o.jsx)(r.a,{href:"https://www.openpolicyagent.org/docs/policy-language/#using-schemas-to-enhance-the-rego-type-checker",children:"has been informed"}),"\nabout the schema of ",(0,o.jsx)(r.code,{children:"input"}),")."]}),"\n",(0,o.jsxs)(r.table,{children:[(0,o.jsx)(r.thead,{children:(0,o.jsxs)(r.tr,{children:[(0,o.jsx)(r.th,{children:"Stage"}),(0,o.jsx)(r.th,{children:"Category"}),(0,o.jsx)(r.th,{children:"Message"})]})}),(0,o.jsx)(r.tbody,{children:(0,o.jsxs)(r.tr,{children:[(0,o.jsx)(r.td,{children:(0,o.jsx)(r.code,{children:"compilation"})}),(0,o.jsx)(r.td,{children:(0,o.jsx)(r.code,{children:"rego_type_error"})}),(0,o.jsx)(r.td,{children:(0,o.jsx)(r.code,{children:"match error left: <type1> right: <type2>"})})]})})]}),"\n",(0,o.jsx)(r.h2,{id:"examples",children:"Examples"}),"\n",(0,o.jsx)(r.p,{children:"The first example is trivial, but serves well to demonstrate the error. An equality check between two literals of\ndifferent type can never be true, and the compiler knows this:"}),"\n",(0,o.jsx)(r.pre,{children:(0,o.jsx)(r.code,{className:"language-rego",children:'package policy\n\nimport future.keywords.if\n\nsame if 1 == "1"\n'})}),"\n",(0,o.jsx)(r.p,{children:"The error message reported will include the types compared in the match error:"}),"\n",(0,o.jsx)(r.pre,{children:(0,o.jsx)(r.code,{className:"language-txt",children:"1 error occurred: policy.rego:5: rego_type_error: match error\n    left  : number\n    right : string\n"})}),"\n",(0,o.jsx)(r.p,{children:'Some cases are more tricky however, and even comparison between two values of the same "simple" type can render a match\nerror when composite types are on both sides of the comparison. Consider the following example:'}),"\n",(0,o.jsx)(r.pre,{children:(0,o.jsx)(r.code,{className:"language-rego",children:'package policy\n\nimport future.keywords.if\n\nuser1 := {"name": "joe", "age": 55}\nuser2 := {"name": "jane"}\n\nsame_user if user1 == user2\n'})}),"\n",(0,o.jsx)(r.p,{children:"Two objects are being compared here. Should this really be a match error? The compiler would say yes:"}),"\n",(0,o.jsx)(r.pre,{children:(0,o.jsx)(r.code,{className:"language-txt",children:"1 error occurred: policy.rego:8: rego_type_error: match error\n    left  : object<age: number, name: string>\n    right : object<name: string>\n"})}),"\n",(0,o.jsxs)(r.p,{children:["The reason is that while objects appear on both sides, the type checker compares ",(0,o.jsx)(r.em,{children:"recursively"}),". In doing\nthis it'll see that one object has an attribute (",(0,o.jsx)(r.code,{children:"age"}),") that the other doesn't, and hence considered to be of\ndifferent type after all. This is sometimes considered\n",(0,o.jsx)(r.a,{href:"https://github.com/open-policy-agent/opa/issues/2132",children:"confusing"}),", but given that it also allows catching some bugs at\ncompile time, it's likely the right behavior."]}),"\n",(0,o.jsx)(r.h2,{id:"how-to-fix-it",children:"How To Fix It"}),"\n",(0,o.jsxs)(r.p,{children:["Fixing this requires changing the types to match on both sides of a comparison. For the few cases where one\n",(0,o.jsx)(r.em,{children:"really"}),' wants to compare two values of different types, a helper function can be used to "wash" off the type\ninformation from the comparison:']}),"\n",(0,o.jsx)(r.pre,{children:(0,o.jsx)(r.code,{className:"language-rego",children:'package policy\n\nimport future.keywords.if\n\nuser1 := {"name": "joe", "age": 55}\nuser2 := {"name": "jane"}\n\nuntyped_equals(o1, o2) if o1 == o2\n\n# this will be undefined, not a compile time error\nsame_user if untyped_equals(user1, user2)\n'})}),"\n",(0,o.jsx)(r.p,{children:"Do note \u2014 this is not a recommended approach! The type checker is there to help you, and circumventing it should be\ndone only in exceptional cases."})]})}function d(e={}){const{wrapper:r}={...(0,s.R)(),...e.components};return r?(0,o.jsx)(r,{...e,children:(0,o.jsx)(l,{...e})}):l(e)}}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.