apple/pkl · critical · VmException
Stack overflow
Error message
Stack overflow
What it means
When a command-spec value converter triggers a Pkl stack overflow, CommandSpecParser.handleErrors converts it: if VmUtils.isPklBug(e) says the overflow is a Pkl internal issue, it is re-thrown as a VmException with message 'Stack overflow' marked as a bug, attaching the original cause. Otherwise the exception is converted normally with its evaluation frames. Receiving the 'bug' variant means stack exhaustion occurred inside Pkl's own machinery rather than user recursion.
Source
Thrown at pkl-core/src/main/java/org/pkl/core/runtime/CommandSpecParser.java:1090
&& vmTyped.getVmClass() == CommandModule.getImportClass();
}
// handle errors from convert/transformAll and correctly format them for the CLI
private Object handleBadValue(Supplier<Object> f) {
try {
return handleErrors(f);
} catch (Throwable e) {
// add a newline so this prints nicely under "Error: invalid value for <name>:"
throw new BadValue("\n" + e.getMessage());
}
}
private <T> T handleErrors(Supplier<T> f) {
try {
return f.get();
} catch (VmStackOverflowException e) {
if (VmUtils.isPklBug(e)) {
throw new VmExceptionBuilder()
.bug("Stack overflow")
.withCause(e.getCause())
.build()
.toPklException(frameTransformer, color);
}
throw e.toPklException(frameTransformer, color);
} catch (VmException e) {
throw e.toPklException(frameTransformer, color);
} catch (Exception e) {
throw new PklBugException(e);
}
}
// for convert, handle imports by replacing Command.Import values
// with imported module or Mapping<String, Module> values
// Command.Import instances in returned Pair, List, Set, or Map values are replaced as well
// other types or nested instances of the above are not affected
private Object handleImports(Object result, URI workingDirUri) {View on GitHub (pinned to f3efcbfc9b)
Solutions
- Report this to the Pkl project as a bug; include the cause/stack trace attached to the VmException.
- Reduce recursion depth in the Pkl code executed by the converter (rewrite recursion as fold/loop).
- Increase the evaluation/stack limits only as a workaround; the error indicates an internal defect, not expected user error.
Defensive patterns
Strategy: try-catch
Validate before calling
// bound recursion in Pkl code invoked by converters fun depth(n: Int, max: Int = 1000): Int = if (n >= max) max else depth(n + 1)
Try / catch
try {
convert(value)
} catch (e: StackOverflowError) {
throw IllegalArgumentException("input too deeply nested for converter")
} Prevention
- Rewrite recursive Pkl logic iteratively where possible
- Report isPklBug=true stack overflows upstream with the cause chain
- Keep converter inputs shallow and validate structure first
When it happens
Trigger: A convert/transformAll function evaluated by the CLI engine recurses until VmStackOverflowException is raised, and the frames indicate a Pkl-internal defect (isPklBug true).
Common situations: Deeply recursive Pkl expressions evaluated during CLI value conversion; evaluator bugs in generators/collections that recurse infinitely; very large nested inputs to converters.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Node `%s` of type `%s` does not have a property named `%s`.
- JavaType token must be parameterized.
- Leaf node `%s` of type `%s` does not have a child named `%s`
- Node `%s` of type `%s` does not have a key named `%s`. Avail
- Did not find expected Java class `%s` on the classpath for P
AI-assisted analysis of apple/pkl@f3efcbfc9b (2026-09-08).
Data as JSON: /api/errors/323bb092fa50379a.
Report an issue: GitHub.