gastownhall/beads · error

linear.outbound_state_map.%s = %q does not match any Linear

Error message

linear.outbound_state_map.%s = %q does not match any Linear workflow state

What it means

The outbound override linear.outbound_state_map.<status> names a Linear state that does not exist in the workspace's state cache (compared case- and whitespace-insensitively by name). The resolver rejects the push rather than guessing, because the override is meant to name one exact state.

Source

Thrown at internal/linear/mapping.go:395

		return "", fmt.Errorf("no workflow states found")
	}
	if config == nil || len(config.ExplicitStateMap) == 0 {
		return "", fmt.Errorf("%s", missingExplicitStateMapMessage)
	}

	// Outbound override: an explicit linear.outbound_state_map.<status> entry
	// names the exact Linear workflow state to push to and short-circuits the
	// name/type matching below. This is the escape hatch when multiple Linear
	// states share a type (e.g. "In Progress" and "In Review" are both
	// "started") and the type-based fallback would otherwise be ambiguous.
	if outboundName, ok := config.OutboundStateMap[strings.ToLower(strings.TrimSpace(string(status)))]; ok {
		want := strings.ToLower(strings.TrimSpace(outboundName))
		for _, state := range cache.States {
			if strings.ToLower(strings.TrimSpace(state.Name)) == want {
				return state.ID, nil
			}
		}
		return "", fmt.Errorf("linear.outbound_state_map.%s = %q does not match any Linear workflow state", status, outboundName)
	}

	var nameMatches []State
	for _, state := range cache.States {
		mapped, ok := config.ExplicitStateMap[strings.ToLower(strings.TrimSpace(state.Name))]
		if ok && stateMapMatchesStatus(mapped, status) {
			nameMatches = append(nameMatches, state)
		}
	}
	if len(nameMatches) == 1 {
		return nameMatches[0].ID, nil
	}
	if len(nameMatches) > 1 {
		names := make([]string, 0, len(nameMatches))
		for _, state := range nameMatches {
			names = append(names, state.Name)
		}
		return "", fmt.Errorf("linear.state_map maps beads status %q to multiple Linear states: %s", status, strings.Join(names, ", "))

View on GitHub (pinned to 71377f2769)

Solutions

  1. Correct the value of linear.outbound_state_map.<status> to exactly match a Linear state name (case-insensitive).
  2. List current Linear workflow states (re-sync the state cache) and pick a valid name.
  3. Remove the outbound override if it is unnecessary and rely on linear.state_map instead.
  4. Re-run 'bd linear link' after Linear-side renames to refresh mappings.
  5. Verify the override targets a state in the same team the integration is scoped to.

Example fix

// before
[linear.outbound_state_map]
in_progress = "InProgress"   # no such state
// after
[linear.outbound_state_map]
in_progress = "In Progress"
Defensive patterns

Strategy: validation

Validate before calling

func validateOutboundOverrides(cfg *linear.MappingConfig, cache *linear.StateCache) error {
	for status, name := range cfg.OutboundStateMap {
		found := false
		for _, s := range cache.States {
			if strings.EqualFold(strings.TrimSpace(s.Name), strings.TrimSpace(name)) {
				found = true
				break
			}
		}
		if !found {
			return fmt.Errorf("outbound_state_map.%s references unknown Linear state %q", status, name)
		}
	}
	return nil
}

Try / catch

stateID, err := linear.ResolveStateIDForBeadsStatus(cache, status, cfg)
if err != nil && strings.Contains(err.Error(), "outbound_state_map") {
	return fmt.Errorf("fix linear.outbound_state_map: %v", err)
}

Prevention

When it happens

Trigger: Calling ResolveStateIDForBeadsStatus when config has an outbound_state_map entry for the status, but no State in cache.States has a matching Name — a typo, a renamed Linear state, or a state belonging to a different team.

Common situations: Linear admin renamed 'In Progress' to 'Active' while the beads config still references the old name; config copied from another workspace; trailing-space or casing mistakes the trim/lower comparison can't fix because the name simply doesn't exist.

Related errors


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