gastownhall/beads · error

failed to fetch team labels: %w

Error message

failed to fetch team labels: %w

What it means

GetTeamLabels calls Linear's GraphQL API page-by-page to collect all issue labels for a team. Any error returned from the underlying Execute call (transport failure, HTTP error, GraphQL error) is wrapped with this prefix so callers know the failure happened while fetching label pages.

Source

Thrown at internal/linear/client.go:699

	var after *string
	for {
		vars := map[string]interface{}{
			"teamId": c.TeamID,
			"first":  pageSize,
			"after":  nil,
		}
		if after != nil {
			vars["after"] = *after
		}

		req := &GraphQLRequest{
			Query:     query,
			Variables: vars,
		}

		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")

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped cause (%w chain) for the actual transport/HTTP/GraphQL error and address it specifically.
  2. Verify the API key is valid and not expired by calling a trivial query (e.g. `viewer { id }`).
  3. Retry the call with backoff if the cause is a 429 or transient network error — Linear rate limits are documented in response headers.
  4. Check network/proxy configuration if the cause is connection-level (timeouts, DNS, TLS).

Example fix

// before
if err != nil {
    return nil, fmt.Errorf("failed to fetch team labels: %w", err)
}
// after
if err != nil {
    var rlErr *RateLimitError
    if errors.As(err, &rlErr) {
        time.Sleep(rlErr.RetryAfter)
        continue // retry this page
    }
    return nil, fmt.Errorf("failed to fetch team labels (page %d): %w", pageNum, err)
}
Defensive patterns

Strategy: retry

Validate before calling

if os.Getenv("LINEAR_API_KEY") == "" {
    return errors.New("LINEAR_API_KEY not set")
}
// optional preflight:
// resp, err := http.Post(endpoint, ..., `{"query":"{ viewer { id } }"}`)

Try / catch

labels, err := client.GetTeamLabels(ctx)
if err != nil {
    var netErr net.Error
    if errors.As(err, &netErr) && netErr.Timeout() {
        // retry with backoff
    }
    return fmt.Errorf("label cache build failed: %w", err)
}

Prevention

When it happens

Trigger: c.Execute fails during any pagination iteration: network timeout, non-2xx HTTP status, invalid/expired API key, rate limiting (429), or GraphQL errors in the response body.

Common situations: Expired or rotated LINEAR_API_KEY, corporate proxy/firewall blocking api.linear.app, Linear rate limits hit while paginating many label pages, transient DNS or TLS failures.

Related errors


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