{"record":{"id":"19ef0d0c668339bd","repo":"github/copilot-sdk","slug":"session-is-closed","errorCode":null,"errorMessage":"Session is closed","messagePattern":"Session is closed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"java/sdk/src/main/java/com/github/copilot/CopilotSession.java","lineNumber":2510,"sourceCode":"     * @return a future that completes when compaction finishes\n     * @throws IllegalStateException\n     *             if this session has been terminated\n     * @since 1.0.11\n     */\n    public CompletableFuture<Void> compact() {\n        ensureNotTerminated();\n        return rpc.invoke(\"session.compaction.compact\", Map.of(\"sessionId\", sessionId), Void.class);\n    }\n\n    /**\n     * Verifies that this session has not yet been terminated.\n     *\n     * @throws IllegalStateException\n     *             if close() has already been invoked\n     */\n    private void ensureNotTerminated() {\n        if (isTerminated) {\n            throw new IllegalStateException(\"Session is closed\");\n        }\n    }\n\n    /**\n     * Disposes the session and releases all associated resources.\n     * <p>\n     * This destroys the session on the server, clears all event handlers, and\n     * releases tool and permission handlers. After calling this method, the session\n     * cannot be used again. Subsequent calls to this method have no effect.\n     */\n    @Override\n    public void close() {\n        synchronized (this) {\n            if (isTerminated) {\n                return; // Already terminated - no-op\n            }\n            isTerminated = true;\n        }","sourceCodeStart":2492,"sourceCodeEnd":2528,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/java/sdk/src/main/java/com/github/copilot/CopilotSession.java#L2492-L2528","documentation":"CopilotSession tracks termination internally; once close() has been invoked, every subsequent API call passes through ensureNotTerminated(), which throws IllegalStateException('Session is closed'). The SDK does this to prevent RPC dispatch on a disposed transport and to make use-after-close explicit rather than hanging or failing obscurely.","triggerScenarios":"Any CopilotSession public method (e.g. setModel, send requests) called after session.close(), or when a shutdown/termination sequence already ran (CopilotSession.java:2510).","commonSituations":"Async callbacks or listeners that outlive the session fire after close(); lifecycle races where a timeout handler closes the session while another thread still submits work; double-close followed by reuse.","solutions":["Check session state (or track closed status yourself) before invoking session methods.","Restructure shutdown so all in-flight work completes or is cancelled before close() is called.","Recreate a new CopilotSession if continued operation is required after termination.","Synchronize session usage so callbacks cannot run concurrently with close()."],"exampleFix":"// before\nsession.close();\nsession.setModel(options); // IllegalStateException\n// after\nsession.close();\nsession = createNewSession();\nsession.setModel(options);","handlingStrategy":"try-catch","validationCode":"if (sessionClosed) {\n    return CompletableFuture.failedFuture(new IllegalStateException(\"session already closed\"));\n}","typeGuard":"boolean isUsable(CopilotSession s) { return s != null && !s.isClosed(); }","tryCatchPattern":"try {\n    session.setModel(options);\n} catch (IllegalStateException e) {\n    LOG.warning(\"session closed, re-creating: \" + e.getMessage());\n    session = createNewSession();\n    session.setModel(options);\n}","preventionTips":["Guard all callbacks and async tasks against session shutdown.","Close the session only after cancelling or awaiting in-flight work.","Track session lifecycle centrally instead of sharing the reference across owners."],"tags":["illegal-state","use-after-close","lifecycle"],"backgroundTag":"invalid-state-transition","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}