apple/pkl · error

expectedNonNullValue

expectedNonNullValue

Error message

expectedNonNullValue

What it means

Thrown by the non-null assertion operator `!!` when its operand evaluates to null. The error is reported at the operand's source section so the developer can see which expression was null. Pkl's `!!` is a deliberate runtime assertion that a value is non-null.

Solutions

  1. Look at the highlighted operand expression; check why it evaluates to null.
  2. Replace `!!` with an explicit null check or use `??` to supply a default value.
  3. If the operand is an absent property, ensure the upstream module actually defines/sets it.
  4. Use `isNonNullable`/instanceof tests to guard before applying `!!`.

Example fix

// before
val port = externalConfig?.port!!
// after
val port = externalConfig?.port ?? 8080
Defensive patterns

Strategy: type-guard

Validate before calling

val port = if (cfg?.port != null) cfg.port else 8080

Type guard

function requireNonNull<T>(v: T|null, msg: String): T =
  if (v == null) throw new Error(msg) else v

Try / catch

try {
  value = operand!!
} catch (e) {
  // e.code === 'expectedNonNullValue': operand was null; supply default
}

Prevention

When it happens

Trigger: Evaluating `x!!` where `x` is null — e.g. an optional property that was never set, a `read()` on a missing resource returning null, or a Map/List lookup producing null followed by `!!`.

Common situations: Asserting non-null on property lookups that may be absent, parsing external data with optional fields, using `!!` defensively instead of providing defaults.

Related errors


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

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/unary/NonNullNode.java:41

import org.pkl.core.runtime.VmNull;

@NodeInfo(shortName = "!!")
// Truffle DSL/codegen is overkill for this node, hence don't extend UnaryExpressionNode
public final class NonNullNode extends ExpressionNode {
  private @Child ExpressionNode operandNode;

  public NonNullNode(SourceSection sourceSection, ExpressionNode operandNode) {
    super(sourceSection);
    this.operandNode = operandNode;
  }

  @Override
  public Object executeGeneric(VirtualFrame frame) {
    var operand = operandNode.executeGeneric(frame);
    if (!(operand instanceof VmNull)) return operand;

    CompilerDirectives.transferToInterpreter();
    throw exceptionBuilder()
        .evalError("expectedNonNullValue")
        .withSourceSection(operandNode.getSourceSection())
        .build();
  }
}

View on GitHub (pinned to f3efcbfc9b)