apple/pkl · error · VmException

cannotFindKey ${key} in Map

Error message

cannotFindKey ${key} in Map

What it means

Subscripting a Map with a key that is absent throws 'cannotFindKey ${key} in Map'. Pkl maps require explicit key existence; there is no implicit null for missing keys. The message identifies the missing key and the Map type.

Source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/binary/SubscriptNode.java:77

  @Specialization
  protected Object eval(VmList receiver, long index) {
    if (index < 0 || index >= receiver.getLength()) {
      CompilerDirectives.transferToInterpreter();
      throw exceptionBuilder()
          .evalError("elementIndexOutOfRange", index, 0, receiver.getLength() - 1)
          .withProgramValue("Collection", receiver)
          .build();
    }
    return receiver.get(index);
  }

  @Specialization
  protected Object eval(VmMap receiver, Object key) {
    var result = receiver.getOrNull(key);
    if (result != null) return result;

    CompilerDirectives.transferToInterpreter();
    throw exceptionBuilder().cannotFindKey(receiver, key).build();
  }

  @Specialization
  protected Object eval(
      VmListing listing, long index, @Exclusive @Cached("create()") IndirectCallNode callNode) {

    var result = VmUtils.readMemberOrNull(listing, index, callNode);
    if (result != null) return result;

    CompilerDirectives.transferToInterpreter();
    throw exceptionBuilder()
        .evalError("elementIndexOutOfRange", index, 0, listing.getLength() - 1)
        .build();
  }

  @Specialization
  protected Object eval(
      VmMapping mapping, Object key, @Exclusive @Cached("create()") IndirectCallNode callNode) {

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Use `map.getOrNull(key)` (or `getOrDefault`) and handle the missing case
  2. Verify the key exists and matches exactly (type, case, spelling)
  3. Add the key to the Map definition or fix the data source

Example fix

// before (Pkl)
val region = config["Region"]
// after
val region = config["region"] ?? "us-east-1"
Defensive patterns

Strategy: fallback

Validate before calling

function safeMapGet(map, key, dflt) { return Object.prototype.hasOwnProperty.call(map, key) ? map[key] : dflt; }

Type guard

const hasKey = (m, k) => m != null && Object.prototype.hasOwnProperty.call(m, k);

Prevention

When it happens

Trigger: `map[key]` where `map.getOrNull(key)` returns null — key never inserted, key of wrong type/value (e.g. Int vs String), or case mismatch in string keys.

Common situations: Typo'd or case-mismatched config keys, expecting defaults from environment data that isn't present, or using a value as key where a symbol/type is expected.

Related errors


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