apple/pkl · error

operatorNotDefinedLeft

operatorNotDefinedLeft

Error message

operatorNotDefinedLeft ${op} ${leftClass}

What it means

Short-circuiting nodes (`&&`, `||`) require the left operand to be Boolean; when no specialization matches the left type, the fallback throws `operatorNotDefinedLeft` naming the operator and the left operand's class. Unlike 542/543 (right side), here the LEFT side of the logical operator is not a Boolean.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/binary/ShortCircuitingExpressionNode.java:44

/**
 * A binary expression whose right operand may be short-circuited. Does not inherit from
 * BinaryExpressionNode for technical reasons.
 */
@NodeChild(value = "leftNode", type = ExpressionNode.class)
public abstract class ShortCircuitingExpressionNode extends ExpressionNode {
  @Child protected ExpressionNode rightNode;

  protected abstract ExpressionNode getLeftNode();

  protected ShortCircuitingExpressionNode(SourceSection sourceSection, ExpressionNode rightNode) {
    super(sourceSection);
    this.rightNode = rightNode;
  }

  @Fallback
  @TruffleBoundary
  protected Object fallback(Object left) {
    throw operatorNotDefined(left);
  }

  @TruffleBoundary
  protected VmException operatorNotDefined(Object left) {
    return exceptionBuilder()
        .evalError("operatorNotDefinedLeft", getShortName(), VmUtils.getClass(left))
        .withProgramValue("Left operand", left)
        .build();
  }

  @TruffleBoundary
  protected VmException operatorNotDefined(Object left, Object right) {
    return exceptionBuilder()
        .evalError(
            "operatorNotDefined2", getShortName(), VmUtils.getClass(left), VmUtils.getClass(right))
        .withProgramValue("Left operand", left)
        .withProgramValue("Right operand", right)
        .build();

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Fix the left operand to be a Boolean expression
  2. Add the missing comparison that converts the value to Boolean
  3. Annotate the source property as Boolean

Example fix

// before (Pkl)
val ok = retries && retries > 3
// after
val ok = retries > 0 && retries > 3
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidLeftOperand(left) { return typeof left === 'boolean'; }

Type guard

const isBool = (v) => typeof v === 'boolean';

Prevention

When it happens

Trigger: `<nonBoolean> && ...` or `<nonBoolean> || ...`, e.g. `1 && true`, `"yes" || false`, or a lazily-evaluated left property of wrong type.

Common situations: Condition written against a config property whose type changed (Int/String instead of Boolean), or inverted/missing comparison.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08). Data as JSON: /api/errors/38491dd5e88f6ac3. Report an issue: GitHub.