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 {
						hasNextPage

View on GitHub (pinned to 71377f2769)

Solutions

  1. 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.
  2. Check the API key scope/permissions — regenerate a Linear API key with access to the target team.
  3. Inspect the raw response for a GraphQL `errors` array and surface it instead of only checking nil.
  4. 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

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


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