gastownhall/beads · error
failed to fetch teams: %w
Error message
failed to fetch teams: %w
What it means
FetchTeams queries the teams GraphQL field to discover team IDs. This error wraps any Execute failure — network errors, HTTP status errors, GraphQL errors like insufficient scopes — when listing teams. It is typically the first call made when configuring the integration, so it is the first place auth problems surface.
Source
Thrown at internal/linear/client.go:1428
query := `
query {
teams {
nodes {
id
name
key
}
}
}
`
req := &GraphQLRequest{
Query: query,
}
data, err := c.Execute(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to fetch teams: %w", err)
}
var teamsResp TeamsResponse
if err := json.Unmarshal(data, &teamsResp); err != nil {
return nil, fmt.Errorf("failed to parse teams response: %w", err)
}
return teamsResp.Teams.Nodes, nil
}
// FetchProjects retrieves projects from Linear with optional filtering by state.
// state can be: "planned", "started", "paused", "completed", "canceled", or "all"/"".
func (c *Client) FetchProjects(ctx context.Context, state string) ([]Project, error) {
var allProjects []Project
var cursor string
filter := map[string]interface{}{
"team": map[string]interface{}{View on GitHub (pinned to 71377f2769)
Solutions
- Unwrap the error to identify the underlying cause (status code / GraphQL message).
- Verify the API key in Linear settings → API; regenerate if revoked and update the environment/config.
- Test connectivity: curl the Linear GraphQL endpoint from the same host.
- Check for 429 rate-limit errors and add backoff/retry around the call.
- Ensure the token's OAuth scopes include team read access.
Example fix
// before
team, err := client.FetchTeams(ctx)
// after
team, err := client.FetchTeams(ctx)
if err != nil {
var rl *RateLimitError
if errors.As(err, &rl) { time.Sleep(rl.RetryAfter); return client.FetchTeams(ctx) }
return fmt.Errorf("team discovery failed (check LINEAR_API_KEY): %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
// sanity-check configuration before calling
if os.Getenv("LINEAR_API_KEY") == "" {
return fmt.Errorf("LINEAR_API_KEY not set")
}
if len(os.Getenv("LINEAR_API_KEY")) < 20 {
return fmt.Errorf("LINEAR_API_KEY looks truncated")
} Try / catch
teams, err := client.FetchTeams(ctx)
if err != nil {
if strings.Contains(err.Error(), "401") || strings.Contains(err.Error(), "authentication") {
return fmt.Errorf("invalid or expired Linear API key: %w", err)
}
if isRetryable(err) {
return retryWithBackoff(3, 2*time.Second, func() error {
_, err = client.FetchTeams(ctx); return err
})
}
return err
} Prevention
- Use FetchTeams as the canonical setup-time health check for the token.
- Add exponential backoff with jitter for 429 responses.
- Store the API key in a secret manager; check expiry/rotation on daemon startup.
- Give the context a timeout so hung connections fail fast and retryably.
When it happens
Trigger: c.Execute fails on `query { teams { nodes { id name key } } }`: invalid/expired API key (401), token missing teams read scope, rate limiting, network unreachable, or context cancellation.
Common situations: Initial setup with a mistyped LINEAR_API_KEY; org admin revoked the integration token; workspace SSO enforcing token rotation; firewall blocking linear.app; expired OAuth token in a long-lived daemon.
Related errors
- failed to fetch issue by identifier: %w
- failed to fetch projects: %w
- failed to parse update response: %w
- batch create failed and recovery search also failed: %w (bat
- batch create failed; %d of %d issues unconfirmed (batch erro
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/938f53d1792c8a3a.
Report an issue: GitHub.