gastownhall/beads · error
ErrAmbiguousID
ErrAmbiguousID
Error message
ambiguous issue ID
What it means
ErrAmbiguousID is the sentinel wrapped into the error ResolvePartialID returns when a partial (abbreviated) issue ID matches more than one issue. It lets callers distinguish 'ambiguous' from 'not found' via errors.Is and surface the candidate list instead of a generic failure. Declared in internal/utils/id_parser.go.
Source
Thrown at internal/utils/id_parser.go:18
// Package utils provides utility functions for issue ID parsing and resolution.
package utils
import (
"context"
"errors"
"fmt"
"sort"
"strings"
"github.com/steveyegge/beads/internal/types"
)
// ErrAmbiguousID is the sentinel wrapped into the error ResolvePartialID
// returns when a partial ID matches more than one issue. Callers use
// errors.Is(err, ErrAmbiguousID) to distinguish "ambiguous" from
// "not found" and surface the candidate list instead of a generic failure.
var ErrAmbiguousID = errors.New("ambiguous issue ID")
type PartialIDResolverStore interface {
SearchIssues(ctx context.Context, query string, filter types.IssueFilter) ([]*types.Issue, error)
SearchIssueIDs(ctx context.Context, query string, filter types.IssueFilter) ([]string, error)
GetConfig(ctx context.Context, key string) (string, error)
}
// parseIssueID ensures an issue ID has the configured prefix.
// If the input already has the prefix (e.g., "bd-a3f8e9"), returns it as-is.
// If the input lacks the prefix (e.g., "a3f8e9"), adds the configured prefix.
// Works with hierarchical IDs too: "a3f8e9.1.2" → "bd-a3f8e9.1.2"
func parseIssueID(input string, prefix string) string {
if prefix == "" {
prefix = "bd-"
}
if strings.HasPrefix(input, prefix) {
return inputView on GitHub (pinned to 71377f2769)
Solutions
- Use the full, unique issue ID (e.g. bd-123) instead of the partial prefix.
- Lengthen the prefix until it matches exactly one issue.
- Inspect the candidate list in the wrapped error and pick the intended issue.
- List matching issues (bd list with the prefix as a query) to disambiguate.
Example fix
// before
id, err := utils.ResolvePartialID(ctx, store, "bd-1") // ambiguous
// after
id, err := utils.ResolvePartialID(ctx, store, "bd-123")
if errors.Is(err, utils.ErrAmbiguousID) {
// surface err's candidate list to the user
} Defensive patterns
Strategy: try-catch
Validate before calling
ids, _ := store.SearchIssueIDs(ctx, partial, types.IssueFilter{})
if len(ids) != 1 {
// disambiguate before resolving
} Try / catch
id, err := utils.ResolvePartialID(ctx, store, partial)
if errors.Is(err, utils.ErrAmbiguousID) {
// show candidate list from wrapped error
} Prevention
- Use full IDs in scripts and automation.
- Extend prefixes until unique before passing to commands.
- Surface candidate lists to interactive users instead of guessing.
When it happens
Trigger: Calling ResolvePartialID with a short ID prefix that matches multiple issues, e.g. 'bd-1' matching bd-10, bd-12, bd-123; using an abbreviated ID in commands like bd show, bd close, or bd update where the prefix is not unique.
Common situations: Large backlogs where short numeric prefixes collide; copy-pasting a truncated ID from a teammate; typing 'bd show 12' when bd-12 and bd-123 both exist.
Related errors
- ambiguous ID: %s matches %d issues
- resolving --deps target %q: %w
- failed to resolve %s: %w
- epic '%s' not found: %v
- issue '%s' not found: %v
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/2248503a3dd7461e.
Report an issue: GitHub.