github/copilot-sdk · error

failed to unmarshal sessions response

Error message

failed to unmarshal sessions response: %w

What it means

ListSessions wraps json.Unmarshal failures of the 'session.list' result with this error. The library expects a listSessionsResponse (sessions array); if the backend returns anything not decodable into that struct, this error is surfaced. The underlying decode error is preserved for errors.As inspection.

Solutions

  1. Dump the raw result and compare its shape to listSessionsResponse
  2. Update the client library and backend to matching versions
  3. Decode into json.RawMessage and check the 'sessions' field type manually to diagnose
  4. Retry once in case of a transient truncated response

Example fix

// before
sessions, err := client.ListSessions(ctx)
// after
sessions, err := client.ListSessions(ctx)
if err != nil && strings.Contains(err.Error(), "unmarshal sessions response") {
    log.Printf("backend returned unexpected list shape: %v", err)
}
Defensive patterns

Strategy: try-catch

Type guard

func isSessionsUnmarshalError(err error) bool {
    return strings.Contains(err.Error(), "unmarshal sessions response")
}

Try / catch

sessions, err := client.ListSessions(ctx)
if err != nil {
    if isSessionsUnmarshalError(err) {
        // treat as unknown list shape: retry once, then surface backend/version mismatch
        return nil, fmt.Errorf("list sessions: %w", err)
    }
    return nil, err
}

Prevention

When it happens

Trigger: Calling ListSessions when the backend result cannot decode into listSessionsResponse — e.g. sessions field is an object instead of an array, or the result is an error string.

Common situations: Backend/client version mismatch after upgrade; corrupted IPC stream; backend returning an error payload where a list was expected.

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

Appendix: source

Thrown at go/client.go:1552

//
//	sessions, err := client.ListSessions(context.Background(), &SessionListFilter{Repository: "owner/repo"})
func (c *Client) ListSessions(ctx context.Context, filter *SessionListFilter) ([]SessionMetadata, error) {
	if err := c.ensureConnected(ctx); err != nil {
		return nil, err
	}

	params := listSessionsRequest{}
	if filter != nil {
		params.Filter = filter
	}
	result, err := c.client.Request(ctx, "session.list", params)
	if err != nil {
		return nil, err
	}

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

	return response.Sessions, nil
}

// GetSessionMetadata returns metadata for a specific session by ID.
//
// This provides an efficient O(1) lookup of a single session's metadata
// instead of listing all sessions. Returns nil if the session is not found.
//
// Example:
//
//	metadata, err := client.GetSessionMetadata(context.Background(), "session-123")
//	if err != nil {
//	    log.Fatal(err)
//	}
//	if metadata != nil {
//	    fmt.Printf("Session started at: %s\n", metadata.StartTime)

View on GitHub (pinned to cd8cf15dc3)