gastownhall/beads · error

failed to parse issues response: %w

Error message

failed to parse issues response: %w

What it means

FetchIssues failed to JSON-unmarshal the 'data' payload returned by Linear into IssuesResponse. This means the response shape didn't match the client's expected `issues.nodes`/`pageInfo` structure.

Source

Thrown at internal/linear/client.go:511

			"first":  MaxPageSize,
		}
		if cursor != "" {
			variables["after"] = cursor
		}

		req := &GraphQLRequest{
			Query:     issuesQuery,
			Variables: variables,
		}

		data, err := c.Execute(ctx, req)
		if err != nil {
			return nil, fmt.Errorf("failed to fetch issues: %w", err)
		}

		var issuesResp IssuesResponse
		if err := json.Unmarshal(data, &issuesResp); err != nil {
			return nil, fmt.Errorf("failed to parse issues response: %w", err)
		}

		allIssues = append(allIssues, issuesResp.Issues.Nodes...)

		if !issuesResp.Issues.PageInfo.HasNextPage {
			break
		}
		cursor = issuesResp.Issues.PageInfo.EndCursor
	}

	return allIssues, nil
}

// FetchIssuesSince retrieves issues from Linear that have been updated since the given time.
// This enables incremental sync by only fetching issues modified after the last sync.
// The state parameter can be: "open", "closed", or "all".
// If ProjectID is set on the client, only issues from that project are returned.
func (c *Client) FetchIssuesSince(ctx context.Context, state string, since time.Time) ([]Issue, error) {

View on GitHub (pinned to 71377f2769)

Solutions

  1. Log the raw data payload (json.RawMessage) to see the actual response shape
  2. Compare issuesQuery against Linear's current GraphQL schema
  3. Upgrade the client/beads to a version matching Linear's current API
  4. If a field type changed, update the Issue/IssuesResponse structs accordingly

Example fix

// after: capture the raw payload for diagnosis
data, err := c.Execute(ctx, req)
if err != nil { return nil, err }
log.Printf("linear raw page: %s", string(data))
var issuesResp IssuesResponse
if err := json.Unmarshal(data, &issuesResp); err != nil {
    return nil, fmt.Errorf("failed to parse issues response: %w", err)
}
Defensive patterns

Strategy: try-catch

Type guard

// Guard against a truncated/nil issues node before use
func validIssuesResponse(raw json.RawMessage) bool {
    var probe struct {
        Issues *struct {
            PageInfo struct{ HasNextPage bool } `json:"pageInfo"`
        } `json:"issues"`
    }
    return json.Unmarshal(raw, &probe) == nil && probe.Issues != nil
}

Try / catch

issues, err := client.FetchIssues(ctx, "all")
if err != nil && strings.Contains(err.Error(), "failed to parse issues response") {
    // likely Linear schema drift: capture payload via debug logging, stop retrying
    return fmt.Errorf("client/API version mismatch: %w", err)
}

Prevention

When it happens

Trigger: Execute returned successfully but the data payload doesn't fit IssuesResponse: Linear API schema change (fields renamed/removed in issuesQuery), a partial-data response, or unexpected nullability causing decode mismatches.

Common situations: Linear shipped a GraphQL schema change and the vendored client's query/response structs are outdated; a proxy/intercepting layer mangled the JSON; running an old beads binary against a newer Linear API.

Understand the failure class

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/2f8918b34254aed0. Report an issue: GitHub.