oracle/graal · error · PermanentBailoutException
Number of elements in a node list too high: %d
Error message
Number of elements in a node list too high: %d
What it means
NodeList is the backing store for a node's plural inputs/outputs, and its size must fit a char (MAX_ENTRIES, 65535) because the graph-dumping protocol serializes list lengths as a 16-bit short. checkMaxSize throws PermanentBailoutException when a list would exceed that hard limit. 'Permanent' tells the compilation framework not to retry: this graph can never be compiled by this backend.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/graph/NodeList.java:124
this.size = 0;
this.nodes = Node.EMPTY_ARRAY;
this.initialSize = 0;
} else {
int newSize = elements.size();
checkMaxSize(newSize);
this.size = newSize;
this.initialSize = newSize;
this.nodes = new Node[elements.size()];
for (int i = 0; i < elements.size(); i++) {
this.nodes[i] = elements.get(i);
assert this.nodes[i] == null || !this.nodes[i].isDeleted();
}
}
}
private static void checkMaxSize(int value) {
if (value > MAX_ENTRIES) {
throw new PermanentBailoutException("Number of elements in a node list too high: %d", value);
}
}
/**
* Removes {@code null} values from the list.
*/
public void trim() {
self.incModCount();
int newSize = 0;
for (int i = 0; i < size; ++i) {
if (nodes[i] != null) {
nodes[newSize] = nodes[i];
newSize++;
}
}
GraalError.guarantee(newSize <= size, "size cannot increase when removing nulls");
size = newSize;
}View on GitHub (pinned to a66e9ccd1d)
Solutions
- Restructure the generated method: split the giant merge/call into several smaller merges or methods so no single node list exceeds 65535 entries.
- If you control the source, reduce the number of predecessors (e.g. chunk large switch tables or chained merges into groups).
- Accept the bailout: verify the method still runs on the baseline tier (PermanentBailoutException is expected to degrade gracefully).
- Check for pathological graph shape first (a bug in a custom phase accidentally adding predecessors), which is fixable unlike genuinely huge input.
Example fix
// generated code shape that triggers it // before: one merge with 100k predecessors merge(allStatements()); // after: chunked merges keep each list small merge(chunk(allStatements(), 50_000).map(this::merge).collect(toList()));
Defensive patterns
Strategy: try-catch
Validate before calling
static final int MAX_LIST = 0xFFFF; // mirrors NodeList.MAX_ENTRIES
if (node.inputs().count() > MAX_LIST || predecessorCount > MAX_LIST) {
splitOrRestructure(node); // fix graph shape before it can hit the limit
} Try / catch
try {
compileMethod(target);
} catch (PermanentBailoutException e) {
// method can never JIT-compile under this backend: accept baseline tier or shrink the input method
log.info("Method too large for JIT, falling back to baseline: {}", e.getMessage());
} Prevention
- Cap the fan-in of generated merges/calls in your code generator well below 65535.
- Treat this bailout as permanent for the method: do not retry the same bytecode unchanged.
- Add a generator-level lint that rejects methods whose single construct can exceed the list limit.
When it happens
Trigger: A node accumulating more than 65535 entries in a single input list: a merge/loop with tens of thousands of predecessors, a call node with a gigantic argument list, or an exploded FrameState/usage list from machine-generated Java code. Typically seen when compiling generated code with enormous methods.
Common situations: Compiling code-generator output or templating engines that emit methods with many thousands of statements merged at one point. Bytecode from DSL compilers producing huge switch/merge structures. Not a config error: it is a structural property of the input method; the JVM falls back to the baseline compiler for that method.
Related errors
- Too many nodes in list:
- Graph was permanetly frozen.
- unknown verbosity:
- NodeBitMap was modified between the calls to hasNext() and n
- Could not load Graal NodeClass TYPE field for
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/f6f2ed1ec141e149.
Report an issue: GitHub.