{"record":{"id":"2f212732b2a530f3","repo":"gastownhall/beads","slug":"w-q-matches-d-issues-v-use-more-characters-t","errorCode":null,"errorMessage":"%w: %q matches %d issues: %v\nUse more characters to disambiguate","messagePattern":"%w: %q matches (.+?) issues: (.+?)\nUse more characters to disambiguate","errorType":"validation","errorClass":"ErrAmbiguousID","httpStatus":null,"severity":"error","filePath":"internal/utils/id_parser.go","lineNumber":224,"sourceCode":"\t\t\t\t}\n\t\t\t}\n\t\t\tif exactMatch != \"\" {\n\t\t\t\treturn exactMatch, nil\n\t\t\t}\n\t\t}\n\t}\n\n\tif len(matches) == 0 {\n\t\treturn \"\", fmt.Errorf(\"no issue found matching %q\", input)\n\t}\n\n\t// Sort so the ambiguity error lists IDs deterministically. SearchIssues return\n\t// order is not a contract for ambiguous matches, so sorting by ID pins the same\n\t// message for every storage implementation.\n\tsort.Strings(matches)\n\n\tif len(matches) > 1 {\n\t\treturn \"\", fmt.Errorf(\"%w: %q matches %d issues: %v\\nUse more characters to disambiguate\", ErrAmbiguousID, input, len(matches), matches)\n\t}\n\n\treturn matches[0], nil\n}\n\nfunc partialIDSearchPart(hashPart string) (string, bool) {\n\tif !looksLikePartialIDHash(hashPart) {\n\t\treturn \"\", false\n\t}\n\tsearchPart := hashPart\n\tif idx := strings.LastIndex(hashPart, \"-\"); idx >= 0 && idx < len(hashPart)-1 {\n\t\tsuffix := hashPart[idx+1:]\n\t\tif looksLikePartialIDHash(suffix) {\n\t\t\tsearchPart = suffix\n\t\t}\n\t}\n\treturn searchPart, true\n}","sourceCodeStart":206,"sourceCodeEnd":242,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/utils/id_parser.go#L206-L242","documentation":"The partial ID matched more than one issue, so ResolvePartialID refuses to guess and returns an error wrapping ErrAmbiguousID (detectable with errors.Is). The message lists every matching ID (sorted deterministically) and asks for a longer fragment. This is by design to prevent operating on the wrong issue.","triggerScenarios":"Calling ResolvePartialID with a hash fragment that is a leading prefix of two or more issue hashes — e.g. \"a3\" when both \"bd-a3f8e9\" and \"bd-a3f11\" exist. Only leading-prefix matches count (HasPrefix), so interior substrings do not trigger this.","commonSituations":"Using 1-2 character abbreviations in scripts on databases with thousands of issues; copy-pasting only the first few characters of a hash; a freshly created issue whose hash happens to share a prefix with an existing one.","solutions":["Use more characters of the hash until exactly one match remains (as the error suggests)","Use the full ID copied from `bd show` or `bd list` output","Filter first with `bd search <keywords>` to narrow to one issue, then use its ID","In code, test with errors.Is(err, utils.ErrAmbiguousID) and prompt the user to choose from the listed matches"],"exampleFix":"// before\nid, err := utils.ResolvePartialID(ctx, store, \"a3\", cfg) // ambiguous\n// after\nid, err := utils.ResolvePartialID(ctx, store, \"a3f8e9\", cfg) // longer fragment\nif errors.Is(err, utils.ErrAmbiguousID) {\n    return fmt.Errorf(\"pick one: %v\", err)\n}","handlingStrategy":"type-guard","validationCode":"// Pre-check uniqueness before resolving:\nids, err := store.SearchIssueIDs(ctx, hashFragment, types.IssueFilter{})\nif err == nil && len(ids) > 1 {\n    return fmt.Errorf(\"fragment %q is ambiguous: %v\", hashFragment, ids)\n}","typeGuard":"func isAmbiguousID(err error) bool {\n    return errors.Is(err, utils.ErrAmbiguousID)\n}","tryCatchPattern":"id, err := utils.ResolvePartialID(ctx, store, frag, cfg)\nif isAmbiguousID(err) {\n    // parse the listed matches and ask the user to pick\n    return interactivePick(err.Error())\n}\nif err != nil { return err }","preventionTips":["Use at least 6-8 hash characters in scripts","Pass full IDs when automating — never 1-2 char fragments","Check errors.Is(err, ErrAmbiguousID) and surface the candidate list to users","Prefer `bd search <keywords>` to narrow to one issue before ID resolution"],"tags":["ambiguity","id-resolution","search","go"],"backgroundTag":"ambiguous-id-match","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}