github/copilot-sdk · warning
failed to disconnect session
Error message
failed to disconnect session %s: %w
What it means
CopilotClient.Stop disconnects every registered session and wraps each Session.Disconnect failure with the session's ID. The wrapped error indicates one specific session failed to clean up while the overall Stop still proceeds over the other sessions.
Solutions
- Inspect the wrapped inner error and session ID to identify which session failed.
- Check that the runtime process/connection is healthy before stopping.
- Treat Stop as best-effort: resources are cleared from the client's session map regardless.
- Retry Stop only if the inner error indicates a transient network issue.
Example fix
// before
if err := client.Stop(ctx); err != nil { panic(err) }
// after
if err := client.Stop(ctx); err != nil {
log.Printf("stop partially failed (resources still cleaned up): %v", err)
} Defensive patterns
Strategy: try-catch
Try / catch
if err := client.Stop(ctx); err != nil { for _, e := range unwrapAll(err) { log.Printf("session stop issue: %v", e) } } Prevention
- Keep runtime connection healthy before Stop
- Avoid duplicate Stop calls
- Treat Stop errors as best-effort cleanup notices
When it happens
Trigger: Calling Stop (or ForceStop) when one or more sessions' Disconnect RPC fails, e.g. because the runtime connection is already broken.
Common situations: Network drop before Stop; runtime process already exited; duplicate Stop calls where the second finds dead connections.
Understand the failure class
Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.
Related errors
- unknown error
- failed to gracefully shut down runtime
- timed out gracefully shutting down runtime after
- failed to get events
- failed to decode session detach response
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/9f2af0ee12105b6f.
Report an issue: GitHub.
Appendix: source
Thrown at go/client.go:583
// Example:
//
// if err := client.Stop(); err != nil {
// log.Printf("Cleanup error: %v", err)
// }
func (c *Client) Stop() error {
var errs []error
// Disconnect all active sessions
c.sessionsMux.Lock()
sessions := make([]*Session, 0, len(c.sessions))
for _, session := range c.sessions {
sessions = append(sessions, session)
}
c.sessionsMux.Unlock()
for _, session := range sessions {
if err := session.Disconnect(); err != nil {
errs = append(errs, fmt.Errorf("failed to disconnect session %s: %w", session.SessionID, err))
}
}
c.sessionsMux.Lock()
c.sessions = make(map[string]*Session)
c.sessionsMux.Unlock()
c.clearGitHubTokenProviders()
c.startStopMux.Lock()
defer c.startStopMux.Unlock()
if (c.process != nil || c.ffiHost != nil) && !c.isExternalServer && c.RPC != nil {
rpcClient := c.RPC
runtimeShutdownStart := time.Now()
shutdownDone := make(chan error, 1)
go func() {
_, err := rpcClient.Runtime.Shutdown(context.Background())
shutdownDone <- errView on GitHub (pinned to cd8cf15dc3)