apple/pkl · error · VmException
cannotIterateOverThisValue
cannotIterateOverThisValue
Error message
Cannot iterate over value of type `{0}`. What it means
Pkl's `...` spread operator was applied to a value that evaluated to `null`, so the generator cannot iterate it. Pkl throws this instead of silently skipping the spread. The error suggests using `...?` (nullable spread) which skips null values.
Solutions
- Use the nullable spread operator `...?` instead of `...` to skip null values.
- Guard the value before spreading: `...(options ?? [])`.
- Fix the upstream expression so it returns an empty List/Map instead of null.
Example fix
// before
foo {
...maybeNullList
}
// after
foo {
...?maybeNullList
} Defensive patterns
Strategy: type-guard
Validate before calling
if (maybeNull != null) { /* safe to spread */ } Type guard
function isSpreadable(v) { return v != null && (v is List || v is Map || v is Set || v is IntSeq); } Try / catch
Use `...?expr` so null is skipped rather than thrown.
Prevention
- Prefer `...?` whenever the spread operand may be null.
- Normalize optional inputs with `?? []` before spreading.
- Give optional properties non-null default values (empty List/Map).
When it happens
Trigger: Using `...expr` inside an object literal where `expr` evaluates to `null` (e.g. a property that is null, an external value, or a conditional that produced nothing).
Common situations: Config files where an optional external input (env var, CLI argument, imported property) is null and is spread into a Dynamic/Listing: `...options` where `options = null`.
Related errors
- cannotSpreadObject
- abstractMemberCannotHaveBody
- abstractMethodInNonAbstractType
- array
- Cannot convert pkl.base#Int
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/f0cc34ef5562e161.
Report an issue: GitHub.
Appendix: source
Thrown at pkl-core/src/main/java/org/pkl/core/ast/expression/generator/GeneratorSpreadNode.java:74
this.nullable = nullable;
}
protected abstract void executeWithIterable(
VirtualFrame frame, Object parent, ObjectData data, Object iterable);
@Override
public final void execute(VirtualFrame frame, Object parent, ObjectData data) {
executeWithIterable(frame, parent, data, iterableNode.executeGeneric(frame));
}
@Specialization
@SuppressWarnings("unused")
protected void eval(VmObject parent, ObjectData data, VmNull iterable) {
if (nullable) {
return;
}
CompilerDirectives.transferToInterpreter();
throw exceptionBuilder()
.evalError("cannotIterateOverThisValue", BaseModule.getNullClass())
.withLocation(iterableNode)
.withHint(
"To guard against a nullable value, use `...?` instead of `...`.\n"
+ "Try: `...?"
+ iterableNode.getSourceSection().getCharacters()
+ "`")
.build();
}
@Specialization(guards = "!iterable.isTyped()")
@SuppressWarnings("unused")
protected void eval(VirtualFrame frame, VmDynamic parent, ObjectData data, VmObject iterable) {
doEvalDynamic(frame, data, iterable);
}
@Specialization(guards = "!iterable.isTyped()")
@SuppressWarnings("unused")View on GitHub (pinned to f3efcbfc9b)