{"record":{"id":"b6e174dd446d906f","repo":"gastownhall/beads","slug":"no-issue-found-matching-q-b6e174","errorCode":null,"errorMessage":"no issue found matching %q","messagePattern":"no issue found matching %q","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/utils/id_parser.go","lineNumber":129,"sourceCode":"\t\t// Bare hash or prefix without hyphen: \"a3f8e9\", \"07b8c8\", \"bda3f8e9\" → all get prefix with hyphen added\n\t\tnormalizedID = prefixWithHyphen + input\n\t}\n\n\t// Try exact match on normalized ID using SearchIssues (GH#942)\n\tnormalizedFilter := types.IssueFilter{IDs: []string{normalizedID}}\n\tif issues, err := store.SearchIssues(ctx, \"\", normalizedFilter); err == nil && len(issues) > 0 {\n\t\treturn issues[0].ID, nil\n\t}\n\n\t// If exact match failed, try substring search.\n\t// Use the hash part as a search query to leverage SQL-level filtering\n\t// (id LIKE %hash%) instead of loading ALL issues into memory.\n\t// On large databases (23k+ issues over MySQL wire protocol), loading all\n\t// issues took 60+ seconds; with SQL filtering it's near-instant.\n\thashPart := strings.TrimPrefix(normalizedID, prefixWithHyphen)\n\tsearchPart, ok := partialIDSearchPart(hashPart)\n\tif !ok {\n\t\treturn \"\", fmt.Errorf(\"no issue found matching %q\", input)\n\t}\n\n\t// Narrow projection: this loop only reads the .ID field, so use the\n\t// SearchIssueIDs path instead of SearchIssues. Avoids hydrating all\n\t// 45+ issue columns (including big TEXT fields like description, design,\n\t// notes, metadata, payload) only to discard them.\n\tfilter := types.IssueFilter{}\n\tids, err := store.SearchIssueIDs(ctx, searchPart, filter)\n\tif err != nil {\n\t\treturn \"\", fmt.Errorf(\"failed to search issues: %w\", err)\n\t}\n\n\tvar matches []string\n\tvar exactMatch string\n\n\tfor _, id := range ids {\n\t\t// Check for exact full ID match first (case: user typed full ID with different prefix)\n\t\tif id == input {","sourceCodeStart":111,"sourceCodeEnd":147,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/utils/id_parser.go#L111-L147","documentation":"ResolvePartialID falls back to a substring search of the ID hash when exact matches fail. partialIDSearchPart validates the hash portion is searchable (e.g. non-empty, reasonable length); if it rejects the hash, no lookup can be performed and the function reports that no issue matches the input.","triggerScenarios":"Input that normalizes to an empty or invalid hash part — e.g. passing just the prefix \"bd-\", \"bd\" with no hash, or a string that strips to nothing after TrimPrefix of prefixWithHyphen.","commonSituations":"Users typing only a prefix in place of an ID; scripts passing empty or whitespace-ish tokens as issue IDs; cross-prefix inputs whose hash extraction yields nothing searchable.","solutions":["Pass a real ID or hash fragment (e.g. \"a3f8e9\" or \"bd-a3f8e9\") instead of a bare prefix","Trim/validate user input before calling: reject empty strings and prefix-only values","Run `bd list` without an ID filter to find the correct issue, then retry with its real ID"],"exampleFix":"// before\nid, err := utils.ResolvePartialID(ctx, store, \"bd-\") // no issue found matching \"bd-\"\n// after\ninput := strings.TrimSpace(raw)\nif input == \"\" || strings.TrimPrefix(input, \"bd-\") == \"\" { return fmt.Errorf(\"provide an issue ID\") }\nid, err := utils.ResolvePartialID(ctx, store, input)","handlingStrategy":"validation","validationCode":"func searchableID(input, prefix string) bool {\n\thash := strings.TrimPrefix(strings.TrimPrefix(input, prefix+\"-\"), prefix)\n\treturn hash != \"\"\n}\n// reject prefix-only inputs before calling ResolvePartialID","typeGuard":"func looksLikeIssueID(input string) bool {\n\tinput = strings.TrimSpace(input)\n\treturn input != \"\" && strings.TrimPrefix(input, \"bd-\") != \"\"\n}","tryCatchPattern":"id, err := utils.ResolvePartialID(ctx, store, input)\nif err != nil {\n\tif strings.Contains(err.Error(), \"no issue found matching\") {\n\t\treturn fmt.Errorf(\"%q is not a valid issue ID; run 'bd list' to find one\", input)\n\t}\n\treturn err\n}","preventionTips":["Validate user input: require a hash fragment, not just a prefix","Trim whitespace from IDs before resolution","Provide 'bd list' guidance in CLI help when ID resolution fails"],"tags":["go","id-resolution","partial-id","input-validation"],"backgroundTag":"issue-id-not-found","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}