github/copilot-sdk · error

failed to unmarshal getLastId response

Error message

failed to unmarshal getLastId response: %w

What it means

GetLastSessionID wraps json.Unmarshal failures of the 'session.getLastId' result with this error. The library expects getLastSessionIDResponse; any deviation in the payload produces this wrapped error.

Solutions

  1. Log the raw result to see the actual payload
  2. Verify at least one session exists (ListSessions) before calling
  3. Update client library and backend to matching versions
  4. Handle the error as 'no decodable last session' and fall back to creating a new session

Example fix

// before
id, err := client.GetLastSessionID(ctx)
if err != nil { return err }
// after
id, err := client.GetLastSessionID(ctx)
if err != nil {
    if strings.Contains(err.Error(), "getLastId") {
        return client.NewSession(ctx)
    }
    return err
}
Defensive patterns

Strategy: fallback

Type guard

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

Try / catch

id, err := client.GetLastSessionID(ctx)
if err != nil {
    if isLastIDUnmarshalError(err) {
        id = "" // fall back to creating a new session
    } else {
        return err
    }
}

Prevention

When it happens

Trigger: Calling GetLastSessionID when the backend's last-session-id result cannot decode into getLastSessionIDResponse (wrong type, e.g. number instead of string for sessionId).

Common situations: Fresh install where the backend has never created a session and returns an unexpected null/empty shape; version drift after upgrade.

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/d98031d6e9688c83. Report an issue: GitHub.

Appendix: source

Thrown at go/client.go:1669

//	}
//	if lastID != nil {
//	    session, err := client.ResumeSession(context.Background(), *lastID, &copilot.ResumeSessionConfig{
//	        OnPermissionRequest: copilot.PermissionHandler.ApproveAll,
//	    })
//	}
func (c *Client) GetLastSessionID(ctx context.Context) (*string, error) {
	if err := c.ensureConnected(ctx); err != nil {
		return nil, err
	}

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

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

	return response.SessionID, nil
}

// GetForegroundSessionID returns the ID of the session currently displayed in the TUI.
//
// This is only available when connecting to a server running in TUI+server mode
// (--ui-server). Returns nil if no foreground session is set.
//
// Example:
//
//	sessionID, err := client.GetForegroundSessionID()
//	if err != nil {
//	    log.Fatal(err)
//	}
//	if sessionID != nil {
//	    fmt.Printf("TUI is displaying session: %s\n", *sessionID)

View on GitHub (pinned to cd8cf15dc3)