oracle/graal · warning · RetryableBailoutException
Graph too large to safely compile in reasonable time. Graph
Error message
Graph too large to safely compile in reasonable time. Graph contains more than %d basic blocks
What it means
ControlFlowGraph.identifyBlocksImpl counts one HIRBlock per AbstractBeginNode; block indices are stored in bounded data structures, so exceeding AbstractControlFlowGraph.LAST_VALID_BLOCK_INDEX triggers a RetryableBailoutException stating the graph is too large to compile safely. Retryable means the compilation is re-attempted with a degraded configuration (e.g., less inlining) rather than permanently failing.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/cfg/ControlFlowGraph.java:409
}
}
@SuppressWarnings("try")
private void identifyBlocks(boolean makeModifiable) {
try (DebugCloseable a = CFG_Build.start(graph.getDebug())) {
identifyBlocksImpl(makeModifiable);
}
}
private void identifyBlocksImpl(boolean makeModifiable) {
int numBlocks = 0;
for (AbstractBeginNode begin : graph.getNodes(AbstractBeginNode.TYPE)) {
GraalError.guarantee(begin.predecessor() != null || (begin instanceof AbstractMergeNode || begin instanceof StartNode), "Disconnected control flow %s encountered", begin);
HIRBlock block = makeModifiable ? new HIRBlock.ModifiableBlock(begin, this) : new HIRBlock.UnmodifiableBlock(begin, this);
identifyBlock(block);
numBlocks++;
if (numBlocks > AbstractControlFlowGraph.LAST_VALID_BLOCK_INDEX) {
throw new RetryableBailoutException("Graph too large to safely compile in reasonable time. Graph contains more than %d basic blocks",
AbstractControlFlowGraph.LAST_VALID_BLOCK_INDEX);
}
}
reversePostOrder = ReversePostOrder.identifyBlocks(this, numBlocks);
buildConfig.modifiableBlocks = makeModifiable;
}
@Override
public int getNumberOfLoops() {
return loops.size();
}
public double localLoopFrequency(LoopBeginNode lb) {
return localLoopFrequencyData.get(lb).getLoopFrequency();
}
public ProfileSource localLoopFrequencySource(LoopBeginNode lb) {
return localLoopFrequencyData.get(lb).getProfileSource();View on GitHub (pinned to a66e9ccd1d)
Solutions
- Confirm the retry path succeeds: a RetryableBailout normally recompiles with more conservative settings — only intervene if compilation ultimately fails
- Reduce graph growth: less inlining (smaller MaximumInlineSize / more conservative profiles), less loop explosion, smaller methods
- Split the giant method into smaller compilation units
- If compiling generated code, cap the size of the largest generated methods
Example fix
# before: unbounded eager inlining grows one graph past the block limit -Dgraal.MaximumInlineSize=1000 # after: keep graphs within the limit -Dgraal.MaximumInlineSize=200 # plus split the largest generated methods
Defensive patterns
Strategy: retry
Try / catch
// Compiler retries internally on RetryableBailoutException; harness-level fallback:
try { g = compile(m); } catch (RetryableBailoutException e) { g = compileWithConservativeInlining(m); } Prevention
- Keep graphs bounded: moderate inlining budgets and modest generated-method sizes
- Watch for this after raising inlining/unrolling options aggressively
- Split very large generated methods before AOT compilation
When it happens
Trigger: A graph with more than the hard block-index limit (LAST_VALID_BLOCK_INDEX) basic blocks: gigantic methods, explosive inlining, or loop explosion/full unrolling that multiplies branch structure past the limit.
Common situations: AOT-compiling huge generated dispatch methods; eager inlining of interpreter loops in Truffle; raising inlining/unrolling budgets to extremes; machine-generated state machines.
Related errors
- OSR entry point wasn't parsed
- FullUnroll : Graph seems to grow out of proportion
- LogFile substitution %s cannot be combined with any other ch
- Set the JVMCI_VERSION_CHECK environment variable to "ignore"
- Unknown argument: %s
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/3d66f9d8695d26d7.
Report an issue: GitHub.