oracle/graal · critical · TooManyDeoptimizationsError
deopt taken too many times: {} {}
Error message
deopt taken too many times: {} {} What it means
ForceDeoptSpeculationPhase exists to detect deoptimization loops: when a forced deopt (ForceDeoptValueNode, enabled by the -Dgraal.Deoptimize* testing options) fires again on recompiled code, the speculation fails and the graph is recompiled without it. After getMaximumDeoptCount() failures the phase throws TooManyDeoptimizationsError (ForceDeoptSpeculationPhase.java:150) to break the cycle.
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/ForceDeoptSpeculationPhase.java:150
for (int i = 0; i < getMaximumDeoptCount(graph); i++) {
SpeculationLog.SpeculationReason reason = VERIFY_SPECULATION.createSpeculationReason(signature.getSignature(), signature.getId(deopt), i);
if (graph.getSpeculationLog().maySpeculate(reason)) {
return graph.getSpeculationLog().speculate(reason);
}
}
throw reportTooManySpeculationFailures(deopt);
}
@SuppressWarnings("unused")
protected int getMaximumDeoptCount(StructuredGraph graph) {
return recompileCount;
}
/**
* Report a deopt cycle.
*/
protected GraalError reportTooManySpeculationFailures(ValueNode deopt) {
throw new TooManyDeoptimizationsError("deopt taken too many times: " + deopt + " " + getDeoptSummary(deopt.graph().getProfilingInfo()));
}
}
View on GitHub (pinned to a66e9ccd1d)
Solutions
- Remove or narrow the -Dgraal.Deoptimize* option so the affected method is no longer forced to deopt
- If this is an intentional stress test, accept the error or raise the recompile/deopt budget option used by getMaximumDeoptCount
- Check DeoptimizeMethodFilter/DeoptimizeOnly filters for a pattern that unintentionally matches the failing method
Example fix
# before java -Dgraal.DeoptimizeALot=true MyApp # after java -Dgraal.DeoptimizeALot=true -Dgraal.DeoptimizeOnly=com.foo.StableBench.myApp MyApp
Defensive patterns
Strategy: try-catch
Try / catch
// when programmatically compiling with force-deopt options
try {
compiled = compile(options);
} catch (TooManyDeoptimizationsError e) {
// deopt cycle confirmed: drop the force-deopt option and recompile
options = optionsWithout(DeoptimizeOptions);
compiled = compile(options);
} Prevention
- Scope -Dgraal.Deoptimize* stress options with DeoptimizeOnly/DeoptimizeMethodFilter to stable methods
- Treat this error in tests as the expected termination of a deopt-loop experiment, not a crash
When it happens
Trigger: Compiling with a force-deopt testing option (e.g., -Dgraal.DeoptimizeALot, DeoptimizeMethodFilter/DeoptimizeOnly, or playground-style deopt injection) where the marked code keeps deoptimizing across recompilations until the recompile budget is exhausted.
Common situations: Stress-testing configurations left enabled in benchmarks; a method filter that keeps matching hot methods whose deopts never stabilize; intentionally cyclic deopt tests that exceed the configured maximum.
Related errors
- Graph was permanetly frozen.
- unknown verbosity:
- NodeBitMap was modified between the calls to hasNext() and n
- Could not load Graal NodeClass TYPE field for
- accessing node id in %s across %d graph compression%s
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/b67ec5c31c1e2d72.
Report an issue: GitHub.