gastownhall/beads · error
linear.state_map type fallback is ambiguous for beads status
Error message
linear.state_map type fallback is ambiguous for beads status %q across Linear states: %s. Set linear.outbound_state_map.%s = "<state name>" to disambiguate
What it means
No state name matched, so the resolver fell back to matching by Linear state type (via linear.state_map.<type> entries), but multiple Linear states share that type (e.g. 'In Progress' and 'In Review' are both 'started'). The error lists the candidates and tells the user exactly how to disambiguate with an outbound_state_map override.
Source
Thrown at internal/linear/mapping.go:431
return "", fmt.Errorf("linear.state_map maps beads status %q to multiple Linear states: %s", status, strings.Join(names, ", "))
}
var typeMatches []State
for _, state := range cache.States {
mapped, ok := config.ExplicitStateMap[strings.ToLower(strings.TrimSpace(state.Type))]
if ok && stateMapMatchesStatus(mapped, status) {
typeMatches = append(typeMatches, state)
}
}
if len(typeMatches) == 1 {
return typeMatches[0].ID, nil
}
if len(typeMatches) > 1 {
names := make([]string, 0, len(typeMatches))
for _, state := range typeMatches {
names = append(names, state.Name)
}
return "", fmt.Errorf("linear.state_map type fallback is ambiguous for beads status %q across Linear states: %s. Set linear.outbound_state_map.%s = \"<state name>\" to disambiguate", status, strings.Join(names, ", "), status)
}
return "", fmt.Errorf("linear.state_map has no configured Linear state for beads status %q", status)
}
// ParseBeadsStatus converts a status string to types.Status.
func ParseBeadsStatus(s string) types.Status {
switch strings.ToLower(s) {
case "open":
return types.StatusOpen
case "in_progress", "in-progress", "inprogress":
return types.StatusInProgress
case "blocked":
return types.StatusBlocked
case "closed", "done":
return types.StatusClosed
case "deferred":
return types.StatusDeferredView on GitHub (pinned to 71377f2769)
Solutions
- Set linear.outbound_state_map.<status> = "<state name>" to name the exact push target, as the error message instructs.
- Add a name-level linear.state_map entry for one specific state instead of the shared type.
- Restructure the Linear workflow so the target status is unique per type if you control the workflow.
- Re-run 'bd linear link' to generate an unambiguous mapping.
Example fix
// before [linear.state_map] started = "in_progress" # matches both 'In Progress' and 'In Review' // after [linear.state_map] started = "in_progress" [linear.outbound_state_map] in_progress = "In Progress"
Defensive patterns
Strategy: fallback
Validate before calling
func needsOutboundOverride(cfg *linear.MappingConfig, cache *linear.StateCache) bool {
counts := map[string]int{}
for _, s := range cache.States {
if _, ok := cfg.ExplicitStateMap[strings.ToLower(strings.TrimSpace(s.Type))]; ok {
counts[strings.ToLower(s.Type)]++
}
}
for t, n := range counts {
if n > 1 {
fmt.Printf("type %q matches %d states; configure linear.outbound_state_map\n", t, n)
return true
}
}
return false
} Try / catch
stateID, err := linear.ResolveStateIDForBeadsStatus(cache, status, cfg)
if err != nil && strings.Contains(err.Error(), "Set linear.outbound_state_map") {
return fmt.Errorf("push blocked; %v", err) // surface the built-in remediation hint
} Prevention
- Whenever multiple Linear states share a type, configure linear.outbound_state_map for affected statuses.
- Prefer name-level state_map entries over type-level in custom workflows.
- Run 'bd linear link' which detects ambiguity and prompts for overrides.
- Keep type fallback as a pull-only convenience; never rely on it for push.
- Audit the workflow after adding states like 'Code Review' that duplicate an existing type.
When it happens
Trigger: Calling ResolveStateIDForBeadsStatus where the explicit state-name pass found nothing, but the type-fallback pass matched 2+ states whose linear.state_map.<state-type> entry matches the status.
Common situations: Workspace with custom workflow states sharing a type ('Started': 'In Progress', 'Code Review', 'QA'); defaults relying on type matching for pull being reused for push.
Related errors
- linear.state_map maps beads status %q to multiple Linear sta
- no workflow states found
- %s
- linear.outbound_state_map.%s = %q does not match any Linear
- linear.state_map has no configured Linear state for beads st
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/805f183440f32948.
Report an issue: GitHub.