{"record":{"id":"7bd496b1d3ab8be4","repo":"oracle/graal","slug":"recording-failed-due-to-an-exception","errorCode":null,"errorMessage":"Recording failed due to an exception","messagePattern":"Recording failed due to an exception","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"critical","filePath":"compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java","lineNumber":137,"sourceCode":"            Object receiver = worklist.removeLast();\n            CompilerInterfaceDeclarations.Registration registration = declarations.findRegistrationForInstance(receiver);\n            for (CompilerInterfaceDeclarations.MethodCallToRecord methodCall : registration.getMethodCallsToRecord(receiver)) {\n                OperationRecorder.RecordedOperationKey key = new OperationRecorder.RecordedOperationKey(methodCall.receiver(), methodCall.symbolicMethod(), methodCall.args());\n                if (recorder.getRecordedResultOrMarker(key) != SpecialResultMarker.NO_RESULT_MARKER) {\n                    // The result of the call is already recorded.\n                    continue;\n                }\n                try {\n                    Object result = methodCall.invokableMethod().invoke(methodCall.receiver(), methodCall.args());\n                    recorder.recordReturnValue(key, result);\n                    // Make sure to record the method calls for the results of this call as well.\n                    worklistAdder.proxifyRecursive(result);\n                } catch (InvocationTargetException e) {\n                    Throwable cause = e.getCause();\n                    recorder.recordExceptionThrown(key, cause);\n                    worklistAdder.proxifyRecursive(cause);\n                } catch (IllegalAccessException e) {\n                    throw new IllegalStateException(\"Recording failed due to an exception\", e);\n                }\n            }\n        }\n        return recorder.getCurrentRecordedOperations();\n    }\n\n    @Override\n    public DebugCloseable enterCompilationContext() {\n        return recorder.enterCompilationContext();\n    }\n\n    @Override\n    public DebugCloseable enterSnippetContext() {\n        return recorder.enterIgnoredContext();\n    }\n\n    @Override\n    public Platform targetPlatform() {","sourceCodeStart":119,"sourceCodeEnd":155,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/replaycomp/RecordingCompilationProxies.java#L119-L155","documentation":"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').","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"# before\njava -XX:+UnlockExperimentalVMOptions -Dgraal.ReplaySupport=true ...\n# after: open the compiler packages to reflection\njava --add-opens jdk.internal.vm.compiler/jdk.graal.compiler.hotspot.replaycomp=ALL-UNNAMED ...","handlingStrategy":"try-catch","validationCode":"// Before recording, verify reflective access to the implementation method\nMethod m = recordedCall.invokableMethod();\ntry {\n    m.setAccessible(true);\n    m.canAccess(receiver); // returns false if access would fail\n} catch (RuntimeException e) {\n    throw new IllegalStateException(\"Access not open for \" + m, e);\n}","typeGuard":null,"tryCatchPattern":"catch (IllegalStateException e) {\n    if (e.getCause() instanceof IllegalAccessException iae) {\n        // infrastructure problem: add --add-opens for the member's package, then re-run recording\n        throw new ReplaySetupException(\"Reflective access blocked: \" + iae.getMessage(), iae);\n    }\n    throw e;\n}","preventionTips":["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"],"tags":["graalvm","replay","reflection","module-system"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}