github/copilot-sdk · error

Failed to disconnect session

Error message

Failed to disconnect session ${this.sessionId}: ${response.error || "Unknown error"}

What it means

Thrown during disconnect() when the `session.detach` request (retried up to twice) still reports success:false. The message includes the session id and the error string returned by the host, or "Unknown error" when the response carries no error detail. The session is not marked disconnected in this path.

Solutions

  1. Inspect response.error in the message to see the host-side detach failure and fix that root cause
  2. Retry disconnect() after a short delay — the SDK only retries twice
  3. Check that the connection is still alive before disconnecting; reconnect if the transport dropped
  4. Treat an already-disconnected session as success and skip detach

Example fix

// before
await session.disconnect(); // throws if host reports failure twice
// after
try {
  await session.disconnect();
} catch (err) {
  if (!session.isDisconnected) {
    await new Promise((r) => setTimeout(r, 1000));
    await session.disconnect();
  }
}
Defensive patterns

Strategy: retry

Validate before calling

if (!session.isConnected || session.isDisconnected) return; // nothing to detach
if (session.disconnecting) return; // avoid concurrent disconnects

Try / catch

try {
  await session.disconnect();
} catch (err) {
  if (String(err?.message).startsWith("Failed to disconnect session")) {
    console.warn(`Detach failed: ${err.message}; forcing local cleanup`);
    session.forceCleanup?.();
  } else throw err;
}

Prevention

When it happens

Trigger: Host returns { success: false, error } from session.detach on both attempts; connection-level failure so detach never succeeds; session already torn down server-side with an error status.

Common situations: Flaky or dropped transport mid-disconnect; server busy/restarting during shutdown; calling disconnect concurrently from multiple code paths so the second call detaches an already-detached session and errors.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/4124bcd5c26aa7bc. Report an issue: GitHub.

Appendix: source

Thrown at nodejs/src/session.ts:2081

     * ```typescript
     * // Clean up when done — session can still be resumed later
     * await session.disconnect();
     * ```
     */
    async disconnect(): Promise<void> {
        if (this.disconnected || this.disconnecting) {
            return;
        }
        this.disconnecting = true;
        try {
            let response: { success: boolean; error?: string } = { success: false };
            for (let attempt = 0; attempt < 2 && !response.success; attempt++) {
                response = (await this.connection.sendRequest("session.detach", {
                    sessionId: this.sessionId,
                })) as { success: boolean; error?: string };
            }
            if (!response.success) {
                throw new Error(
                    `Failed to disconnect session ${this.sessionId}: ${response.error || "Unknown error"}`
                );
            }
            this._markDisconnected();
        } catch (error) {
            this.disconnecting = false;
            throw error;
        }
    }

    /** Enables `await using session = ...` syntax for automatic cleanup. */
    async [Symbol.asyncDispose](): Promise<void> {
        return this.disconnect();
    }

    /**
     * Aborts the currently processing message in this session.
     *

View on GitHub (pinned to cd8cf15dc3)