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

  1. Restructure the generated method: split the giant merge/call into several smaller merges or methods so no single node list exceeds 65535 entries.
  2. If you control the source, reduce the number of predecessors (e.g. chunk large switch tables or chained merges into groups).
  3. Accept the bailout: verify the method still runs on the baseline tier (PermanentBailoutException is expected to degrade gracefully).
  4. 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

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


AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14). Data as JSON: /api/errors/f6f2ed1ec141e149. Report an issue: GitHub.