apple/pkl · error · VmException

wrongListingKeyType

wrongListingKeyType

Error message

Expected key of type `Int`, but got type `{0}`.

What it means

Listing amendments (`... { ... } amends a Listing` or List entries) must be keyed by integer indices. `checkIsValidListingAmendment` throws this when a member's key in a Listing amendment is not a `Long`, reporting the actual runtime type of the key.

Solutions

  1. Replace the key with an integer index (`[0]`, `[1]`, ...) appropriate for the element's position
  2. If arbitrary keys are needed, change the container to a `Mapping` instead of a `Listing`
  3. Remove the mis-keyed member if it was added by mistake

Example fix

// before (items is a Listing)
items { ["first"] = 1 }
// after
items { [0] = 1 }
Defensive patterns

Strategy: type-guard

Validate before calling

// Pkl: only use [n] keys in Listing bodies
// if (key is Int) { items { [key] = v } } else { error("Listing keys must be Int indices") }

Type guard

function isIntKey(key: Any): Boolean = key is Int

Prevention

When it happens

Trigger: Writing a Listing amendment with a string identifier key instead of an index, e.g. `items { ["first"] = ... }` where `items` is a `Listing`; using a Boolean, Float, or other key type where an Int index is expected.

Common situations: Confusing `Listing` (positional elements) with `Mapping` (arbitrary keys) — using string keys in a Listing; converting a Mapping-based config to a Listing and forgetting to renumber keys.

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/1a0dc292deb09139. Report an issue: GitHub.

Appendix: source

Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/literal/SpecializedObjectLiteralNode.java:134

  @TruffleBoundary
  @Idempotent
  protected final boolean checkIsValidListingAmendment() {
    if (maxListingMemberIndex != Long.MIN_VALUE) return true;

    var cursor = EconomicMaps.getEntries(members);
    long maxIndex = -1;

    while (cursor.advance()) {
      var member = cursor.getValue();
      if (member.isLocal()) continue;

      var memberName = member.getNameOrNull();
      if (memberName == null) {
        var key = cursor.getKey();

        if (!(key instanceof Long)) {
          CompilerDirectives.transferToInterpreter();
          throw exceptionBuilder()
              .evalError("wrongListingKeyType", new ProgramValue("", VmUtils.getClass(key)))
              .withSourceSection(member.getHeaderSection())
              .build();
        }

        long index = (long) key;
        if (index < 0) {
          // defer handling of negative index to checkMaxListingMemberIndex() (gives more uniform
          // error messages)
          maxIndex = Long.MAX_VALUE;
          break;
        } else if (index > maxIndex) {
          maxIndex = index;
        }
      } else if (memberName != Identifier.DEFAULT) {
        throw exceptionBuilder()
            .evalError("objectCannotHaveProperty", BaseModule.getListingClass())
            .withSourceSection(member.getHeaderSection())

View on GitHub (pinned to f3efcbfc9b)