gastownhall/beads · error
failed to fetch team states: %w
Error message
failed to fetch team states: %w
What it means
GetTeamStates wraps any Execute failure with this message when fetching a team's workflow states. The wrapped cause is the underlying failure: GraphQL error (usually an unknown team ID), auth failure, rate limiting, or network error. Callers like BuildStateCache depend on this succeeding to map states.
Source
Thrown at internal/linear/client.go:645
id
name
type
}
}
}
}
`
req := &GraphQLRequest{
Query: query,
Variables: map[string]interface{}{
"teamId": c.TeamID,
},
}
data, err := c.Execute(ctx, req)
if err != nil {
return nil, fmt.Errorf("failed to fetch team states: %w", err)
}
var teamResp TeamResponse
if err := json.Unmarshal(data, &teamResp); err != nil {
return nil, fmt.Errorf("failed to parse team states response: %w", err)
}
if teamResp.Team.States == nil {
return nil, fmt.Errorf("no states found for team")
}
return teamResp.Team.States.Nodes, nil
}
// GetTeamLabels returns all issue labels defined for the team (paginated).
func (c *Client) GetTeamLabels(ctx context.Context) ([]Label, error) {
const pageSize = 250
query := `View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped cause — 'GraphQL errors: Team not found' almost always means TeamID is wrong
- Verify the team ID by querying Linear for the workspace's teams with the same token
- Regenerate/replace the API key if the wrapped error is 401/403
- Wait for rate-limit reset if the cause is 'max retries' / 'rate limited'
- Confirm the token's scopes include read access to workflow states
Example fix
// before
states, err := client.GetTeamStates(ctx)
// after: distinguish bad team ID from transient failures
if err != nil {
if strings.Contains(err.Error(), "not found") {
log.Fatalf("TeamID %q invalid — list teams with the same token", client.TeamID)
}
return fmt.Errorf("transient, retry later: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// Validate team access before building the state cache
probe := `query { viewer { id } }`
if _, err := client.Execute(ctx, &linear.GraphQLRequest{Query: probe}); err != nil {
return fmt.Errorf("token or connectivity invalid before GetTeamStates: %w", err)
}
if client.TeamID == "" {
return errors.New("linear: TeamID must be configured")
} Try / catch
states, err := client.GetTeamStates(ctx)
if err != nil {
if strings.Contains(err.Error(), "not found") || strings.Contains(err.Error(), "GraphQL errors") {
return fmt.Errorf("configuration error (TeamID=%q): %w", client.TeamID, err) // no retry
}
return retryWithBackoff(ctx, func() ([]linear.State, error) { return client.GetTeamStates(ctx) })
} Prevention
- Confirm TeamID by listing teams with the same token during setup
- Check token scopes include team/state read access
- Throttle state-cache rebuilds to avoid rate limits
- Handle the wrapped cause distinctly: config vs transient
When it happens
Trigger: Calling GetTeamStates (directly or via BuildStateCache) when: the configured TeamID doesn't exist in the workspace (Linear returns 'Team not found' GraphQL error), the API token lacks access to that team, OAuth token refresh failed on 401, or Linear is rate-limiting/unreachable.
Common situations: Misconfigured LINEAR_TEAM_ID (typo or ID from another workspace); token created before the team existed or without team access; hitting rate limits right after a large sync; Linear outage.
Related errors
- failed to update project: %w
- GraphQL error: %s
- failed to marshal request: %w
- failed to fetch issues: %w
- failed to fetch issues since %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/55a7c9be23044a07.
Report an issue: GitHub.