apple/pkl · error
operatorNotDefined1
operatorNotDefined1
Error message
operatorNotDefined1
What it means
Pkl raises `operatorNotDefined1` when a unary operator is applied to an operand whose type does not support it. The UnaryExpressionNode family (e.g. UnaryMinusNode, LogicalNotNode) uses Truffle specializations per type; when no specialization matches, the @Fallback at UnaryExpressionNode.java:34 throws an eval error naming the operator and the operand's class. This is Pkl's way of saying the operand type has no defined semantics for that operator.
Solutions
- Read the error message: it names the operator and the operand's class; locate the operand expression at the reported source location and confirm its actual type.
- Convert or fix the operand so it has the type the operator expects (e.g. use `value.toBoolean()` style conversion or fix the value so `-` applies to Int/Float and `!` applies to Boolean).
- If the operand can legitimately be absent/null, guard the expression, e.g. use the null-propagating form or a conditional instead of the raw operator.
- If the type is dynamic (external input), add an `is`-based type check or a `when`/amend block so the operator is only applied to matching values.
Example fix
// before (pkl) flag: !input.enabled // input.enabled is a String "yes" -> operatorNotDefined1 // after flag: !input.enabled.toBoolean()
Defensive patterns
Strategy: type-guard
Validate before calling
// pkl
if (value is Int || value is Float) { /* safe for unary minus */ }
if (value is Boolean) { /* safe for ! */ } Type guard
function isNumeric(x) = x is Int || x is Float function isBool(x) = x is Boolean
Prevention
- Type-annotate module/class properties so wrong-type values fail at validation, not at the operator.
- Convert external input (env vars, CLI) to the intended type before applying operators.
- Avoid mixing dynamic external values directly into arithmetic/logic expressions.
When it happens
Trigger: Evaluating a unary operator in Pkl code where the operand type is not covered by any specialization, e.g. `-"abc"` (unary minus on String), `!42` (logical not on Int), or applying a unary operator to a Listing/Mapping/typed object or null where no specialization exists. `getShortName()` supplies the operator symbol and `VmUtils.getClass(operand)` supplies the offending operand type in the message.
Common situations: A property intended to be a number is actually a String (so `-value` fails); a boolean property reads null or a non-Boolean from an environment override so `!flag` fails; refactored code changed a property's type (Int -> String) leaving a unary expression behind; applying `!` to the result of a comparison that was removed during editing.
Understand the failure class
Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.
Related errors
- operatorNotDefined2
- operatorNotDefined2
- operatorNotDefined2
- operatorNotDefinedLeft
- abstractMemberCannotHaveBody
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/3883f2e79292536b.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/unary/UnaryExpressionNode.java:34
package org.pkl.core.ast.expression.unary;
import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary;
import com.oracle.truffle.api.dsl.Fallback;
import com.oracle.truffle.api.dsl.NodeChild;
import com.oracle.truffle.api.source.SourceSection;
import org.pkl.core.ast.ExpressionNode;
import org.pkl.core.runtime.VmUtils;
@NodeChild(value = "operandNode", type = ExpressionNode.class)
public abstract class UnaryExpressionNode extends ExpressionNode {
protected UnaryExpressionNode(SourceSection sourceSection) {
super(sourceSection);
}
@Fallback
@TruffleBoundary
protected Object fallback(Object operand) {
throw exceptionBuilder()
.evalError("operatorNotDefined1", getShortName(), VmUtils.getClass(operand))
.withProgramValue("Operand", operand)
.build();
}
}
View on GitHub (pinned to f3efcbfc9b)