oracle/graal · error · IllegalMaterializedRecordException
Stack trace and recorded frames mismatch.
Error message
Stack trace and recorded frames mismatch.
What it means
IllegalMaterializedRecordException thrown while rendering a suspended continuation's diagnostic string: the number of FrameRecords in the materialized frame chain exceeds the length of the captured Java stack trace. The VM's recorded frames and the thread's stack trace disagree, so the pretty-printed dump cannot be produced. It indicates internal inconsistency (often after resuming on a mismatched stack or a VM bug), not a user API-contract violation.
Source
Thrown at espresso/src/org.graalvm.continuations/src/org/graalvm/continuations/ContinuationImpl.java:427
fr = stackFrameHead;
if (frames == null || fr == null) {
sb.append(" with no recorded frames");
return sb.toString();
}
} finally {
unlock(currentState);
}
}
// Collect records in the usual order
int len = frames.length;
FrameRecord[] orderedRecords = new FrameRecord[len];
for (int i = 0; i < len; i++) {
orderedRecords[(len - 1) - i] = fr;
fr = fr.next;
}
if (fr != null) {
throw new IllegalMaterializedRecordException("Stack trace and recorded frames mismatch.");
}
sb.append(" with recorded frames:\n");
for (int i = 0; i < len; i++) {
StackTraceElement e = frames[i];
FrameRecord record = orderedRecords[i];
// Print the nice stack trace element.
sb.append(" ").append(e).append('\n');
// Additionally provide the bci.
sb.append(" Current bytecode index: ").append(record.bci);
sb.append('\n');
sb.append(" Pointers: [");
// We start at 1 because the first slot is always a primitive (the bytecode index).
for (int j = 1; j < record.pointers.length; j++) {
Object pointer = record.pointers[j];
if (pointer == null) {
sb.append("null");
} else if (pointer == this) {View on GitHub (pinned to a66e9ccd1d)
Solutions
- Do not rely on continuation.toString() for programmatic purposes; log state and entry point instead.
- Recreate the continuation and reproduce the failure with minimal stack depth to get usable diagnostics.
- If reproducible, report a bug to the GraalVM/Espresso project with the continuation creation and resume/suspend sequence.
- Ensure producer and consumer run the same GraalVM version when continuations are serialized.
Defensive patterns
Strategy: try-catch
Try / catch
try {
log.debug("suspended at: {}", continuation);
} catch (IllegalMaterializedRecordException e) {
log.debug("continuation {} state={}", id, continuation.getState()); // fall back to state-only logging
} Prevention
- Do not parse continuation.toString() programmatically.
- Keep producer and consumer GraalVM versions aligned for serialized continuations.
- Report reproducible mismatches upstream with the suspend/resume sequence.
When it happens
Trigger: Calling toString()/getRecordedFrames-path diagnostics on a suspended continuation whose stackFrameHead chain is longer than the recorded StackTraceElement[]; typically after tampering with recorded frames, deserializing across incompatible VM versions, or hitting a VM-level bookkeeping bug.
Common situations: Logging a suspended continuation for debugging; serializing a continuation produced by a different java.Continuum implementation version and inspecting it; nightly diagnostics on long-lived suspended continuations.
Related errors
- This VM does not support continuations.
- Continuations must be run on the Java on Truffle JVM with th
- You can't resume an already executing continuation.
- This continuation has already completed successfully.
- This continuation has failed and must be discarded.
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/0c06b82d042b60f1.
Report an issue: GitHub.