oracle/graal · error · IOException
Expecting
Error message
Expecting
What it means
While serializing a graph, GraphProtocol writes the announced node count first and then iterates the actual nodes, verifying at the end that it emitted exactly that many ('Expecting N nodes, but found M'). A mismatch means the node set changed during printing — the count and the iteration disagree — which would corrupt the dump stream, so it fails with IOException. The root cause is always concurrent or reentrant graph mutation while the dump runs.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graphio/GraphProtocol.java:555
final int size = findNodesCount(info);
writeInt(size);
int cnt = 0;
for (Node node : findNodes(info)) {
NodeClass nodeClass = classForNode(node);
findNodeProperties(node, props, info);
writeInt(findNodeId(node));
writePoolObject(nodeClass);
writeByte(hasPredecessor(node) ? 1 : 0);
writeProperties(info, props);
writeEdges(info, node, true);
writeEdges(info, node, false);
props.clear();
cnt++;
}
if (size != cnt) {
throw new IOException("Expecting " + size + " nodes, but found " + cnt);
}
}
private void writeEdges(Graph graph, Node node, boolean dumpInputs) throws IOException {
NodeClass clazz = classForNode(node);
Edges edges = findClassEdges(clazz, dumpInputs);
int size = findSize(edges);
for (int i = 0; i < size; i++) {
Collection<? extends Node> list = findNodes(graph, node, edges, i);
if (isDirect(edges, i)) {
if (list != null && list.size() != 1) {
throw new IOException("Edge " + i + " in " + edges + " is direct, but list isn't singleton: " + list);
}
Node n = null;
if (list != null && !list.isEmpty()) {
n = list.iterator().next();
}
writeNodeRef(n);View on GitHub (pinned to a66e9ccd1d)
Solutions
- Dump only quiescent graphs: freeze the graph (or dump at a phase boundary where the framework guarantees stability).
- Emit dumps from the compilation thread itself at safe checkpoints rather than asynchronously from another thread.
- Ensure custom GraphProtocol hooks (findNodes, getNodes) are pure readers and never mutate the graph.
- Catch the IOException per-dump and retry the dump at the next safe point; a failed dump must not break compilation.
Example fix
// before
new Thread(() -> output.print(graph, ...)).start(); // races compilation
// after
// dump on the compilation thread at a phase boundary (graph quiescent)
phaseSuite.addPhase(new Phase() {
@Override protected void run(StructuredGraph g) { output.print(g, ...); }
}); Defensive patterns
Strategy: try-catch
Validate before calling
// dump only quiescent graphs: trigger from the compilation thread at a phase boundary, // and freeze the graph for the dump window if your embedding allows it
Try / catch
try {
output.print(graph, ...);
} catch (IOException e) {
if (e.getMessage().startsWith("Expecting")) {
// graph mutated during dump: skip this dump, retry at the next safe checkpoint
log.fine("Skipped inconsistent graph dump: " + e.getMessage());
} else throw e;
} Prevention
- Never dump from an asynchronous thread while compilation proceeds.
- Ensure custom GraphProtocol hooks (findNodes, property suppliers) are read-only.
- Treat per-dump IOExceptions as non-fatal: log and continue compiling.
When it happens
Trigger: Another thread (or a callback triggered by node accessors like findNodes/findClassForNode) adds or deletes nodes between the count snapshot and the iteration in writeNodes. Dumping a live, still-compiling graph without freezing it. Custom findNodes overrides that lazily modify the graph.
Common situations: Async dump triggers racing an active compilation thread. Debug hooks that mutate the graph from within property/edge suppliers during printing. Dumping at unsafe points where a phase is mid-rewrite.
Related errors
- Trying to write during graph print.
- Cannot downgrade from minimum required version
- Feature unsupported in version
- Dump properties unsupported in format v.
- Too many nodes in list:
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/1b6e9cc5dd484cbf.
Report an issue: GitHub.