github/copilot-sdk · error

failed to set foreground session

Error message

failed to set foreground session: %s

What it means

SetForegroundSessionID returns this error when the backend explicitly reports the switch failed: setForegroundSessionResponse.Success was false. The backend's error string (or 'unknown error') is included, making this a reported backend-side rejection rather than a decode failure.

Solutions

  1. Read the backend error text embedded after the colon
  2. Verify the target session exists via ListSessions before switching
  3. Refresh the cached session ID (e.g. via GetLastSessionID) and retry
  4. Handle the case where no TUI is attached — the switch cannot be performed

Example fix

// before
err := client.SetForegroundSessionID(ctx, targetID)
if err != nil { panic(err) }
// after
if err := client.SetForegroundSessionID(ctx, targetID); err != nil {
    log.Printf("failed to focus session %s: %v", targetID, err)
    // fall back to listing sessions and picking a valid one
}
Defensive patterns

Strategy: try-catch

Validate before calling

sessions, _ := client.ListSessions(ctx)
if !slices.ContainsFunc(sessions, func(s *SessionInfo) bool { return s.ID == targetSessionID }) {
    return fmt.Errorf("cannot focus: session %s does not exist", targetSessionID)
}

Try / catch

if err := client.SetForegroundSessionID(ctx, id); err != nil {
    if strings.Contains(err.Error(), "failed to set foreground session") {
        // backend refused: read reason, refresh session list and pick a valid ID
        return fmt.Errorf("focus refused: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: Calling SetForegroundSessionID and receiving response.Success == false — e.g. the target session no longer exists or the TUI refuses the switch.

Common situations: Switching to a session that was deleted or never existed; TUI running headless; stale session ID cached in the application.

Related errors


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

Appendix: source

Thrown at go/client.go:1737

		return err
	}

	result, err := c.client.Request(ctx, "session.setForeground", setForegroundSessionRequest{SessionID: sessionID})
	if err != nil {
		return err
	}

	var response setForegroundSessionResponse
	if err := json.Unmarshal(result, &response); err != nil {
		return fmt.Errorf("failed to unmarshal setForeground response: %w", err)
	}

	if !response.Success {
		errorMsg := "unknown error"
		if response.Error != nil {
			errorMsg = *response.Error
		}
		return fmt.Errorf("failed to set foreground session: %s", errorMsg)
	}

	return nil
}

// On subscribes to all session lifecycle events.
//
// Lifecycle events are emitted when sessions are created, deleted, updated,
// or change foreground/background state (in TUI+server mode).
//
// Returns a function that, when called, unsubscribes the handler.
//
// Example:
//
//	unsubscribe := client.On(func(event copilot.SessionLifecycleEvent) {
//	    fmt.Printf("Session %s: %s\n", event.SessionID, event.Type)
//	})
//	defer unsubscribe()

View on GitHub (pinned to cd8cf15dc3)