oracle/graal · critical · IllegalStateException
Recording failed due to an exception
Error message
Recording failed due to an exception
What it means
RecordingCompilationProxies replays each recorded compiler-interface call with reflection: invokableMethod().invoke(...). InvocationTargetException is expected and recorded as the method's thrown exception; IllegalAccessException, however, means the reflective call itself could not be made (access check failed) — a setup/infrastructure failure, so it is wrapped in IllegalStateException('Recording failed due to an exception').
Source
Thrown at compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java:137
Object receiver = worklist.removeLast();
CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(receiver);
for (CompilerInterfaceDeclarations.MethodCallToRecord methodCall : registration.getMethodCallsToRecord(receiver)) {
OperationRecorder.RecordedOperationKey key = new OperationRecorder.RecordedOperationKey(methodCall.receiver(), methodCall.symbolicMethod(), methodCall.args());
if (recorder.getRecordedResultOrMarker(key) != SpecialResultMarker.NO_RESULT_MARKER) {
// The result of the call is already recorded.
continue;
}
try {
Object result = methodCall.invokableMethod().invoke(methodCall.receiver(), methodCall.args());
recorder.recordReturnValue(key, result);
// Make sure to record the method calls for the results of this call as well.
worklistAdder.proxifyRecursive(result);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
recorder.recordExceptionThrown(key, cause);
worklistAdder.proxifyRecursive(cause);
} catch (IllegalAccessException e) {
throw new IllegalStateException("Recording failed due to an exception", e);
}
}
}
return recorder.getCurrentRecordedOperations();
}
@Override
public DebugCloseable enterCompilationContext() {
return recorder.enterCompilationContext();
}
@Override
public DebugCloseable enterSnippetContext() {
return recorder.enterIgnoredContext();
}
@Override
public Platform targetPlatform() {View on GitHub (pinned to a66e9ccd1d)
Solutions
- Add the required --add-opens / --add-exports JVM flags so the recorder module can reflectively invoke the implementation classes
- Verify invokableMethod() applies setAccessible(true) (or uses a MethodHandles.Lookup with access) for non-public methods
- Check the cause chain of the IllegalStateException to see exactly which member failed access, then widen that member's visibility or open its package
Example fix
# before java -XX:+UnlockExperimentalVMOptions -Dgraal.ReplaySupport=true ... # after: open the compiler packages to reflection java --add-opens jdk.internal.vm.compiler/jdk.graal.compiler.hotspot.replaycomp=ALL-UNNAMED ...
Defensive patterns
Strategy: try-catch
Validate before calling
// Before recording, verify reflective access to the implementation method
Method m = recordedCall.invokableMethod();
try {
m.setAccessible(true);
m.canAccess(receiver); // returns false if access would fail
} catch (RuntimeException e) {
throw new IllegalStateException("Access not open for " + m, e);
} Try / catch
catch (IllegalStateException e) {
if (e.getCause() instanceof IllegalAccessException iae) {
// infrastructure problem: add --add-opens for the member's package, then re-run recording
throw new ReplaySetupException("Reflective access blocked: " + iae.getMessage(), iae);
}
throw e;
} Prevention
- Launch the recording JVM with the --add-opens flags covering compiler implementation packages
- Keep recorded compiler-interface methods public, or ensure the recorder's lookup has access
- Distinguish InvocationTargetException (expected, recorded) from IllegalAccessException (fatal) in logging so access problems are visible immediately
When it happens
Trigger: A recorded method's accessibility is blocked at invoke time: the method is non-public and setAccessible failed or was not applied, the receiver is in a module/package not opened to the recorder, or a SecurityManager/JPMS access check rejects the call.
Common situations: Running on a JDK with strong encapsulation where compiler classes are not opened (--add-opens missing); recording interfaces whose implementations moved to non-public classes between versions; security manager policies; custom compiler-interface methods with reduced visibility.
Related errors
- Profile file for path %s exists already
- Invalid replay string table index
- Invalid replay string definition index
- Invalid replay symbolic method index
- Invalid replay symbolic method definition index
AI-assisted analysis of oracle/graal@a66e9ccd1d (2026-08-14).
Data as JSON: /api/errors/7bd496b1d3ab8be4.
Report an issue: GitHub.