{"record":{"id":"dafb6409020d20b5","repo":"oracle/graal","slug":"reading-handle-from-a-closed-scope","errorCode":null,"errorMessage":"Reading handle from a closed scope.","messagePattern":"Reading handle from a closed scope\\.","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java","lineNumber":45,"sourceCode":"import java.io.Closeable;\n\nfinal class LibGraalObjectHandleScope implements Closeable {\n\n    private long handle;\n\n    private LibGraalObjectHandleScope(long handle) {\n        this.handle = handle;\n    }\n\n    @Override\n    public void close() {\n        LibGraalObjectHandles.remove(handle);\n        handle = 0;\n    }\n\n    long getHandle() {\n        if (handle == 0) {\n            throw new IllegalStateException(\"Reading handle from a closed scope.\");\n        }\n        return handle;\n    }\n\n    static LibGraalObjectHandleScope forObject(Object object) {\n        return new LibGraalObjectHandleScope(LibGraalObjectHandles.create(object));\n    }\n}\n","sourceCodeStart":27,"sourceCodeEnd":54,"githubUrl":"https://github.com/oracle/graal/blob/a66e9ccd1d7bf2552883939aa0788dfd0e294aab/compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalObjectHandleScope.java#L27-L54","documentation":"LibGraalObjectHandleScope wraps an object handle allocated from LibGraalObjectHandles; close() removes the handle and zeroes the field. getHandle() throws IllegalStateException('Reading handle from a closed scope.') when the handle is 0, i.e. the scope was already closed (or never initialized with a valid handle). This prevents use of a dangling object-handle registration after it was removed.","triggerScenarios":"Calling getHandle() (directly or via a subclass like a TruffleObjectHandleScope used in try-with-resources) after close() ran — e.g. escaping the scope's lifetime, or reading the handle in a finally block after the resource closed.","commonSituations":"A handle object leaked past its try-with-resources block and used in a later callback; nested scopes closed in the wrong order; error paths that close early and then attempt one more interop call.","solutions":["Keep handle usage strictly inside the scope's lifetime (try-with-resources body).","Null out references when closing so later users fail with a clear NPE instead of reaching the closed scope.","Reorder cleanup so consumers finish reading the handle before close().","On IllegalStateException, re-acquire a fresh scope via LibGraalObjectHandleScope.forObject(obj) if the object is still live."],"exampleFix":"// before\ntry (var scope = LibGraalObjectHandleScope.forObject(obj)) {\n    queued = () -> scope.getHandle();\n}\nqueued.run(); // scope already closed\n// after (use the handle inside the scope, or re-scope later)\ntry (var scope = LibGraalObjectHandleScope.forObject(obj)) {\n    long h = scope.getHandle();\n    queued = () -> use(h);\n}","handlingStrategy":"validation","validationCode":"// Consume the handle strictly inside the scope's lifetime\ntry (LibGraalObjectHandleScope scope = LibGraalObjectHandleScope.forObject(obj)) {\n    long h = scope.getHandle(); // OK here\n    use(h);\n}","typeGuard":null,"tryCatchPattern":"try {\n    long h = scope.getHandle();\n} catch (IllegalStateException e) {\n    if (\"Reading handle from a closed scope.\".equals(e.getMessage())) {\n        try (LibGraalObjectHandleScope fresh = LibGraalObjectHandleScope.forObject(obj)) {\n            h = fresh.getHandle();\n        }\n    }\n}","preventionTips":["Never let scope objects escape their try-with-resources block","Read the handle once and pass the long value onward","Close nested scopes in reverse order"],"tags":["libgraal","truffle","resource-lifecycle","use-after-close","object-handles"],"backgroundTag":null,"analyzedSha":"a66e9ccd1d7bf2552883939aa0788dfd0e294aab","analyzedAt":"2026-08-14T13:58:47.161Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}