github/copilot-sdk · error

unknown error

Error message

unknown error

What it means

This error is returned when a session detach RPC completes but the runtime reports failure without including an error message in its response. The SDK substitutes the placeholder string "unknown error" because the remote side did not populate the Error field. It surfaces from Session.OnClose or Session.OnAction handlers when the underlying detach/canvas operation fails server-side with no detail.

Solutions

  1. Inspect runtime/server logs to find the real failure cause, since the SDK could not extract an error message.
  2. Retry the operation to rule out a transient runtime failure.
  3. Verify runtime and SDK versions are compatible.
  4. If persistent, report to the runtime maintainers that the error field is unpopulated.

Example fix

// before
err := handler.OnClose(ctx, req) // yields 'unknown error'
// after
if err != nil && err.Error() == "unknown error" {
    log.Printf("detach failed with no server detail; check runtime logs")
}
Defensive patterns

Strategy: try-catch

Validate before calling

if resp.Success == false && resp.Error == "" { log.Printf("server failed with no detail") }

Try / catch

if err != nil { if err.Error() == "unknown error" { /* inspect server logs, retry */ } }

Prevention

When it happens

Trigger: Calling a CanvasHandler OnClose or OnAction whose underlying session detach RPC returns success=false with an empty response.Error string.

Common situations: Runtime process crashed mid-request; server returned a malformed or empty error field; protocol version mismatch causing the error detail to be dropped.

Related errors


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

Appendix: source

Thrown at go/session.go:1846

//
// Example:
//
//	// Clean up when done — session can still be resumed later
//	if err := session.Disconnect(); err != nil {
//	    log.Printf("Failed to disconnect session: %v", err)
//	}
func (s *Session) Disconnect() error {
	s.cancelPendingExternalTools()
	result, err := s.client.Request(context.Background(), "session.detach", sessionDetachRequest{SessionID: s.SessionID})
	if err == nil {
		var response sessionDetachResponse
		if decodeErr := json.Unmarshal(result, &response); decodeErr != nil {
			err = fmt.Errorf("failed to decode session detach response: %w", decodeErr)
		} else if !response.Success {
			if response.Error == "" {
				response.Error = "unknown error"
			}
			err = errors.New(response.Error)
		}
	}

	// Local cleanup always runs, even if the detach RPC failed, so callers
	// don't leak in-memory resources (event goroutines, registered
	// providers/handlers) just because the runtime couldn't be reached.
	s.stopEventProcessing()
	s.releaseGitHubTokenProviderRegistration()

	// Clear handlers
	s.handlerMutex.Lock()
	s.handlers = nil
	s.handlerMutex.Unlock()

	s.toolHandlersM.Lock()
	s.toolHandlers = nil
	s.toolHandlersM.Unlock()

View on GitHub (pinned to cd8cf15dc3)