gastownhall/beads · error

finding state for status %s: %w

Error message

finding state for status %s: %w

What it means

This error is returned by Tracker.CreateIssue when it cannot resolve the Linear workflow state ID for the beads issue's status. findStateID builds a state cache via the Linear API and then maps the beads status to a state; any failure fetching states or resolving the mapping is wrapped with "finding state for status %s: %w". It blocks issue creation because Linear requires a valid stateId for new issues.

Source

Thrown at internal/linear/tracker.go:195

		if li != nil {
			ti := linearToTrackerIssue(li)
			return &ti, nil
		}
	}
	return nil, nil
}

func (t *Tracker) CreateIssue(ctx context.Context, issue *types.Issue) (*tracker.TrackerIssue, error) {
	client := t.primaryClient()
	if client == nil {
		return nil, fmt.Errorf("no Linear client available")
	}

	priority := PriorityToLinear(issue.Priority, t.config)

	stateID, err := t.findStateID(ctx, client, issue.Status)
	if err != nil {
		return nil, fmt.Errorf("finding state for status %s: %w", issue.Status, err)
	}

	labelCache, err := BuildLabelCache(ctx, client)
	if err != nil {
		return nil, fmt.Errorf("loading team labels: %w", err)
	}
	labelIDs, unknown := ResolveLabelIDs(issue, labelCache, t.config)
	for _, name := range unknown {
		fmt.Fprintf(os.Stderr, "linear: bead %s: label %q not found on Linear team (skipped)\n", issue.ID, name)
	}

	// Use issue.Description as-is: the sync engine's FormatDescription hook
	// (BuildLinearDescription) has already merged AcceptanceCriteria/Design/Notes
	// into the description before calling CreateIssue. Calling BuildLinearDescription
	// here a second time would duplicate those sections for issues with structured fields.
	description := issue.Description

	// Use idempotent creation when we have enough bead metadata to generate

View on GitHub (pinned to 71377f2769)

Solutions

  1. Verify the status-to-state mapping in your beads Linear config matches actual Linear workflow state names for the target team
  2. Check that your Linear API key is valid, not expired, and has access to the target team's workflow states
  3. Run with debug logging to see the underlying wrapped error from BuildStateCache (network vs. resolution)
  4. Test the Linear GraphQL API connectivity directly (curl the endpoint) to rule out network/proxy issues

Example fix

// before
issue.Status = types.Status("in-progress") // not a beads-canonical status
// after
issue.Status = types.StatusInProgress // canonical beads status that maps cleanly via config
Defensive patterns

Strategy: validation

Validate before calling

if issue.Status != types.StatusOpen && issue.Status != types.StatusInProgress && issue.Status != types.StatusClosed && issue.Status != types.StatusBlocked {
    return fmt.Errorf("unsupported status %q for Linear sync", issue.Status)
}

Type guard

func isSyncableStatus(s types.Status) bool {
    switch s {
    case types.StatusOpen, types.StatusInProgress, types.StatusClosed, types.StatusBlocked:
        return true
    }
    return false
}

Try / catch

created, err := tracker.CreateIssue(ctx, issue)
if err != nil {
    var stateErr *StateResolutionError
    if errors.As(err, nil) || strings.Contains(err.Error(), "finding state for status") {
        // log and defer this issue; do not abort the whole sync
    }
    return err
}

Prevention

When it happens

Trigger: Calling Tracker.CreateIssue with an issue whose Status has no matching Linear workflow state in the target team (e.g. an unrecognized custom status), or when the GraphQL query to list workflow states fails (network error, expired/invalid API key, rate limit).

Common situations: Beads config maps a status to a Linear state name that was renamed or deleted on the Linear side; missing or stale LINEAR_API_KEY; team mismatch (issue routed to a team whose states were not configured); network outage or Linear API rate limiting.

Related errors


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