gastownhall/beads · error

failed to parse team labels response: %w

Error message

failed to parse team labels response: %w

What it means

After a successful Execute in GetTeamLabels, the raw response bytes are unmarshalled into the anonymous pagination struct. If the JSON does not match that shape, the client wraps the unmarshal error with this message so callers know label page parsing failed, not the HTTP call itself.

Source

Thrown at internal/linear/client.go:714

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

		var page struct {
			Team struct {
				Labels *struct {
					Nodes    []Label `json:"nodes"`
					PageInfo struct {
						HasNextPage bool   `json:"hasNextPage"`
						EndCursor   string `json:"endCursor"`
					} `json:"pageInfo"`
				} `json:"labels"`
			} `json:"team"`
		}
		if err := json.Unmarshal(data, &page); err != nil {
			return nil, fmt.Errorf("failed to parse team labels response: %w", err)
		}
		if page.Team.Labels == nil {
			return nil, fmt.Errorf("no labels connection found for team")
		}

		all = append(all, page.Team.Labels.Nodes...)
		if !page.Team.Labels.PageInfo.HasNextPage {
			break
		}
		if page.Team.Labels.PageInfo.EndCursor == "" {
			break
		}
		cursor := page.Team.Labels.PageInfo.EndCursor
		after = &cursor
	}

	return all, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Log/dump the raw `data` bytes on failure to see the actual response shape.
  2. Verify the request URL is the Linear GraphQL endpoint (https://api.linear.app/graphql).
  3. Check the Linear changelog for schema changes to `team.labels` and update the anonymous struct accordingly.
  4. Check for a GraphQL `errors` array in the response — a partial error payload may not match the expected struct.

Example fix

// before
if err := json.Unmarshal(data, &page); err != nil {
    return nil, fmt.Errorf("failed to parse team labels response: %w", err)
}
// after
if err := json.Unmarshal(data, &page); err != nil {
    return nil, fmt.Errorf("failed to parse team labels response: %w (body: %.200s)", err, data)
}
Defensive patterns

Strategy: type-guard

Validate before calling

// ensure the endpoint is the GraphQL API before calling
if !strings.HasSuffix(client.Endpoint, "/graphql") {
    return errors.New("endpoint must be https://api.linear.app/graphql")
}

Type guard

func parseLabelsSafely(data []byte) (labels []linear.Label, ok bool) {
    defer func() { if r := recover(); r != nil { ok = false } }()
    var probe struct {
        Data struct {
            Team struct {
                Labels *struct{ Nodes []linear.Label `json:"nodes"` } `json:"labels"`
            } `json:"team"`
        } `json:"data"`
    }
    if json.Unmarshal(data, &probe) != nil || probe.Data.Team.Labels == nil {
        return nil, false
    }
    return probe.Data.Team.Labels.Nodes, true
}

Try / catch

labels, err := client.GetTeamLabels(ctx)
var uerr *json.UnmarshalTypeError
if errors.As(err, &uerr) {
    log.Printf("labels response shape changed: field %s", uerr.Field)
    // fall back to cached labels
}

Prevention

When it happens

Trigger: Linear returns a payload where data.team.labels doesn't match the expected struct — usually because a GraphQL error partial response was returned, an API version changed field names (e.g. labels → issueLabels), or a proxy returned an HTML/JSON error page.

Common situations: Linear GraphQL schema migrations renaming the labels connection, responses from a wrong endpoint (e.g. hitting the REST API instead of /graphql), HTML error pages from proxies returning 200, malformed JSON truncated responses.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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