{"record":{"id":"eaf80ccae6c3ab37","repo":"gastownhall/beads","slug":"failed-to-search-issues-w-eaf80c","errorCode":null,"errorMessage":"failed to search issues: %w","messagePattern":"failed to search issues: %w","errorType":"console","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/utils/id_parser.go","lineNumber":139,"sourceCode":"\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 {\n\t\t\texactMatch = id\n\t\t\tbreak\n\t\t}\n\n\t\t// Extract hash from each issue using config-aware prefix extraction.\n\t\t// This correctly handles multi-hyphen prefixes (e.g., \"hacker-news-ko4\"\n\t\t// yields hash \"ko4\", not \"news-ko4\" from naive first-hyphen split).\n\t\tvar issueHash string\n\t\tif p := ExtractIssuePrefixKnown(id, knownPrefixes); p != \"\" && strings.HasPrefix(id, p+\"-\") {\n\t\t\tissueHash = id[len(p)+1:]","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/utils/id_parser.go#L121-L157","documentation":"ResolvePartialID resolves a partial or fully-qualified issue ID against the storage backend. After the exact-ID lookup fails, it falls back to a substring search via store.SearchIssueIDs; if that underlying storage call returns an error, it is wrapped with this message. This is a transport/storage failure, not a problem with the input ID itself — the original store error is preserved via %w.","triggerScenarios":"Calling utils.ResolvePartialID (directly or via ResolvePartialIDs) when store.SearchIssueIDs errors — e.g. the database is unreachable, the underlying SQL query fails, the context is cancelled, or the storage driver returns an I/O or wire-protocol error during the substring (LIKE) search.","commonSituations":"Dolt/MySQL daemon not running or crashed mid-session; network drop on a remote (MySQL wire protocol) store; context timeout exceeded on very large databases; schema mismatch after a beads version upgrade; read-only or corrupted data directory.","solutions":["Inspect the wrapped cause with errors.Unwrap or %v on the returned error to see the real storage failure","Verify the storage backend is running and reachable (bd doctor, check the Dolt server / database file)","Re-run with a fresh or longer context deadline; large DBs can exceed short timeouts","If it appeared after an upgrade, check for schema migration steps and run them","Retry once connectivity is restored — this error is transient when caused by network/backend outages"],"exampleFix":"// before\nid, err := utils.ResolvePartialID(ctx, store, \"a3f8\", cfg)\nif err != nil { log.Fatal(err) } // hides the real storage cause\n// after\nid, err := utils.ResolvePartialID(ctx, store, \"a3f8\", cfg)\nif err != nil {\n    if errors.Unwrap(err) != nil {\n        log.Fatalf(\"storage failure: %v\", errors.Unwrap(err)) // show root cause\n    }\n    log.Fatal(err)\n}","handlingStrategy":"try-catch","validationCode":"// Ensure the backend is reachable before resolving:\nif err := store.SearchIssueIDs(ctx, \"probe\", types.IssueFilter{}); err != nil {\n    return fmt.Errorf(\"storage unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"id, err := utils.ResolvePartialID(ctx, store, input, cfg)\nif err != nil {\n    var root error\n    for e := err; e != nil; e = errors.Unwrap(e) { root = e }\n    if ctx.Err() != nil { return fmt.Errorf(\"timed out: %w\", ctx.Err()) }\n    log.Printf(\"search failure root cause: %v\", root)\n    return err // not a not-found case; do not treat as missing issue\n}","preventionTips":["Run `bd doctor` as a preflight to catch backend connectivity issues","Use contexts with sane timeouts and check ctx.Err() on failure","Keep beads and the storage backend on compatible versions (run migrations after upgrades)","Retry once on transient network errors before surfacing to the user"],"tags":["storage","search","error-wrapping","go"],"backgroundTag":"issue-search-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}