apple/pkl · error

elementIndexOutOfRange

elementIndexOutOfRange

Error message

elementIndexOutOfRange ${index} 0 ${max}

What it means

Indexing a List with `[i]` outside the valid range 0..length-1 throws `elementIndexOutOfRange`, displaying the requested index and the maximum valid index. Pkl lists are fixed-size, so there is no auto-growth or negative wraparound.

Source

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

              "charIndexOutOfRange", index, 0, receiver.codePointCount(0, receiver.length()) - 1)
          .withSourceSection(getRightNode().getSourceSection())
          .withProgramValue("String", receiver)
          .build();
    }

    if (Character.isHighSurrogate(receiver.charAt(charIndex))
        && charIndex < receiver.length() - 1
        && Character.isLowSurrogate(receiver.charAt(charIndex + 1))) {
      return receiver.substring(charIndex, charIndex + 2);
    }
    return receiver.substring(charIndex, charIndex + 1);
  }

  @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(

View on GitHub (pinned to f3efcbfc9b)

Solutions

  1. Validate `index >= 0 && index < list.length` before subscripting
  2. Use `list.elementAtOrNull(index)` if available, or guard with `list.isEmpty()`
  3. Fix the index computation (length vs length-1)

Example fix

// before (Pkl)
val last = items[items.length]
// after
val last = items[items.length - 1]
Defensive patterns

Strategy: validation

Validate before calling

function safeListGet(list, i) {
  return Array.isArray(list) && Number.isInteger(i) && i >= 0 && i < list.length ? list[i] : null;
}

Type guard

const inListBounds = (list, i) => Array.isArray(list) && i >= 0 && i < list.length;

Prevention

When it happens

Trigger: `list[index]` with index < 0 or index >= list.length, e.g. `servers[servers.length]` (off-by-one) on an empty or short list.

Common situations: Off-by-one in loops, assuming a list is non-empty, or deriving indices from external config that doesn't match list size.

Related errors


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