github/copilot-sdk · error

failed to unmarshal getForeground response

Error message

failed to unmarshal getForeground response: %w

What it means

GetForegroundSessionID returns this error when the 'session.getForeground' result cannot be unmarshalled into getForegroundSessionResponse. The backend responded but the payload shape did not match the expected struct.

Solutions

  1. Ensure the TUI/backend is fully started before polling for the foreground session
  2. Dump the raw result and compare with getForegroundSessionResponse
  3. Update client and backend to matching versions
  4. Treat this as 'no foreground session' and fall back to GetLastSessionID or a new session

Example fix

// before
id, err := client.GetForegroundSessionID(ctx)
// after
id, err := client.GetForegroundSessionID(ctx)
if err != nil {
    if strings.Contains(err.Error(), "getForeground") { id = "" } // no foreground session
    else { return err }
}
Defensive patterns

Strategy: fallback

Type guard

func isForegroundUnmarshalError(err error) bool {
    return strings.Contains(err.Error(), "getForeground response")
}

Try / catch

id, err := client.GetForegroundSessionID(ctx)
if err != nil {
    if isForegroundUnmarshalError(err) {
        id = "" // no decodable foreground session
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Calling GetForegroundSessionID while the TUI/backend returns a foreground-session payload that does not decode into getForegroundSessionResponse.

Common situations: Calling before the TUI is fully started; backend version mismatch; TUI running in a mode that does not track foreground sessions.

Understand the failure class

Background: "failed to unmarshal" / json.Unmarshal errors: why parsing a response into a Go struct fails and how to fix it — this error's family across 23 libraries.

Related errors


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

Appendix: source

Thrown at go/client.go:1701

//	if err != nil {
//	    log.Fatal(err)
//	}
//	if sessionID != nil {
//	    fmt.Printf("TUI is displaying session: %s\n", *sessionID)
//	}
func (c *Client) GetForegroundSessionID(ctx context.Context) (*string, error) {
	if err := c.ensureConnected(ctx); err != nil {
		return nil, err
	}

	result, err := c.client.Request(ctx, "session.getForeground", getForegroundSessionRequest{})
	if err != nil {
		return nil, err
	}

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

	return response.SessionID, nil
}

// SetForegroundSessionID requests the TUI to switch to displaying the specified session.
//
// This is only available when connecting to a server running in TUI+server mode
// (--ui-server).
//
// Example:
//
//	if err := client.SetForegroundSessionID("session-123"); err != nil {
//	    log.Fatal(err)
//	}
func (c *Client) SetForegroundSessionID(ctx context.Context, sessionID string) error {
	if err := c.ensureConnected(ctx); err != nil {
		return err

View on GitHub (pinned to cd8cf15dc3)