gastownhall/beads · error
no states found for team
Error message
no states found for team
What it means
GetTeamStates fetches a team's workflow states via the Linear GraphQL API and decodes the response into a TeamResponse. If the JSON parses but the team's `states` field is nil, the client cannot distinguish 'team has no states' from a malformed response, so it returns this error rather than a nil pointer later.
Source
Thrown at internal/linear/client.go:654
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 := `
query TeamLabels($teamId: String!, $first: Int!, $after: String) {
team(id: $teamId) {
labels(first: $first, after: $after) {
nodes {
id
name
}
pageInfo {
hasNextPageView on GitHub (pinned to 71377f2769)
Solutions
- Verify the team ID used to build the query resolves — run the same GraphQL query manually with the same API key (curl/Altair) and inspect whether data.team.states comes back null.
- Check the API key scope/permissions — regenerate a Linear API key with access to the target team.
- Inspect the raw response for a GraphQL `errors` array and surface it instead of only checking nil.
- Update the query/TeamResponse struct to match the current Linear GraphQL schema.
Example fix
// before
if teamResp.Team.States == nil {
return nil, fmt.Errorf("no states found for team")
}
// after
if teamResp.Team == nil || teamResp.Team.States == nil {
return nil, fmt.Errorf("no states found for team %q (check team ID and API key scope)", c.TeamID)
} Defensive patterns
Strategy: validation
Validate before calling
if teamID == "" || !uuidRegex.MatchString(teamID) {
return fmt.Errorf("invalid Linear team ID: %q", teamID)
} Type guard
func hasStates(resp *linear.TeamResponse) bool {
return resp != nil && resp.Team != nil && resp.Team.States != nil
} Try / catch
states, err := client.GetTeamStates(ctx)
if err != nil {
if strings.Contains(err.Error(), "no states found for team") {
return fmt.Errorf("team %s unreachable or empty: %w", teamID, err)
}
return err
} Prevention
- Validate the team UUID format before calling GetTeamStates.
- Cache team IDs resolved from viewer.teams rather than hardcoding.
- Keep the API key in one place and verify its team access at startup.
- Watch Linear changelog for workflowStates schema changes.
When it happens
Trigger: The GraphQL response decodes successfully but team.states is null — e.g. the team ID is invalid, the API token lacks access to the team, the query shape no longer matches the Linear schema, or the response is a partial GraphQL error payload where data.team is present but states is missing.
Common situations: Wrong or stale team UUID configured (pointing at a deleted/renamed team), API key scoped to a different team/workspace, Linear schema changes renaming or nesting the `states` field, or a GraphQL errors array returned alongside partial data.
Related errors
- no labels connection found for team
- issue creation reported as unsuccessful
- failed to marshal request: %w
- failed to fetch team states: %w
- failed to fetch team labels: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/a6ea5a6244213d2c.
Report an issue: GitHub.