gastownhall/beads · error
failed to fetch team labels
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.
Solutions
- Inspect the wrapped cause (%w chain) for the actual transport/HTTP/GraphQL error and address it specifically.
- Verify the API key is valid and not expired by calling a trivial query (e.g. `viewer { id }`).
- Retry the call with backoff if the cause is a 429 or transient network error — Linear rate limits are documented in response headers.
- 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
- Preflight the API key with a trivial viewer query at startup.
- Implement exponential backoff for 429 responses.
- Run periodic health checks against api.linear.app.
- Log the unwrapped cause chain for faster diagnosis.
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.
Understand the failure class
Background: "API request failed": what wrapped HTTP errors from external APIs mean and how to find the real cause — this error's family across 29 libraries.
Related errors
- failed to create issue
- failed to search issues by description
- failed to update project
- batch create failed and recovery search also failed
- batch create failed;
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c75a4aafe72aa3fa.
Report an issue: GitHub.
Appendix: 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)