{"record":{"id":"5184a267c0650ed9","repo":"apple/pkl","slug":"type-mismatch-type-constraint-must-be-a-boolean-o","errorCode":null,"errorMessage":"type mismatch: type constraint must be a Boolean or a Function","messagePattern":"type mismatch: type constraint must be a Boolean or a Function","errorType":"exception","errorClass":"VmTypeMismatchException","httpStatus":null,"severity":"error","filePath":"pkl-core/src/main/java/org/pkl/core/ast/type/TypeConstraintNode.java","lineNumber":122,"sourceCode":"          throw new VmTypeMismatchException.Constraint(\n              sourceSection,\n              value,\n              function.getRootNode().getSourceSection(),\n              valueTracker.values());\n        }\n      } else {\n        throw new VmTypeMismatchException.Constraint(\n            sourceSection, value, function.getRootNode().getSourceSection(), null);\n      }\n    }\n  }\n\n  @Fallback\n  protected void fallback(Object object) {\n    // supplying a type constraint that's neither a boolean nor a function\n    // is always fatal (even within a union type), hence throw VmEvalException\n    CompilerDirectives.transferToInterpreter();\n    throw exceptionBuilder()\n        .typeMismatch(object, BaseModule.getBooleanClass(), BaseModule.getFunctionClass())\n        .build();\n  }\n\n  protected static ApplyVmFunction1Node createApplyNode() {\n    return ApplyVmFunction1Node.create();\n  }\n\n  private void initConstraintSlot(VirtualFrame frame) {\n    if (customThisSlot == -1) {\n      CompilerDirectives.transferToInterpreterAndInvalidate();\n      // deferred until execution time s.t. nodes of inlined type aliases get the right frame slot\n      customThisSlot = VmUtils.findCustomThisSlot(frame);\n    }\n  }\n}\n","sourceCodeStart":104,"sourceCodeEnd":139,"githubUrl":"https://github.com/apple/pkl/blob/f3efcbfc9b60d30053b0536d664948d7aa1b8673/pkl-core/src/main/java/org/pkl/core/ast/type/TypeConstraintNode.java#L104-L139","documentation":"Pkl type constraints (`x is T || cond`) must evaluate to a Boolean or be a Function taking the constrained value. TypeConstraintNode.fallback throws a type mismatch when the constraint expression is neither — this is always fatal, even inside union types.","triggerScenarios":"Declaring a type constraint whose body evaluates to a non-Boolean, non-Function value, e.g. `x -> 42`, a constraint returning a String/Number, or referencing a property instead of a predicate.","commonSituations":"Writing a constraint that returns the value itself instead of a comparison; forgetting the comparison in a lambda; supplying an object where a predicate is expected.","solutions":["Make the constraint evaluate to a Boolean (e.g. `x > 0`)","If using a function constraint, ensure it is a `Function1` returning Boolean","Fix expressions that return the value or a non-Boolean result"],"exampleFix":"// before\nx: Int(this)  // constraint yields the value, not a Boolean\n// after\nx: Int(isPositive) where { isPositive = this > 0 }","handlingStrategy":"validation","validationCode":"// constraints must yield Boolean\nif (typeof constraint === \"function\") { /* ok */ } else if (typeof constraint !== \"boolean\") throw new Error(\"constraint must be Boolean or Function\");","typeGuard":"function isBooleanOrFn(x){ return typeof x === \"boolean\" || typeof x === \"function\"; }","tryCatchPattern":"try { evaluateConstraint(x); } catch (e) { if (String(e).includes(\"type constraint\")) throw new Error(\"fix constraint to return Boolean\"); throw e; }","preventionTips":["Ensure constraint bodies end in a Boolean expression","Never return the value itself from a constraint lambda"],"tags":["pkl","type-constraint","type-mismatch"],"backgroundTag":"type-mismatch","analyzedSha":"f3efcbfc9b60d30053b0536d664948d7aa1b8673","analyzedAt":"2026-09-08T13:10:45.570Z","contentChangedAt":"2026-09-08T13:10:45.570Z","schemaVersion":2},"datasetVersion":"2026-09-14T16:17:12.679Z"}