{"record":{"id":"21c57c5f0e39da5f","repo":"gastownhall/beads","slug":"search-issues-with-counts-wisp-dependency-probe-21c57c","errorCode":null,"errorMessage":"search issues with counts: wisp dependency probe: %w","messagePattern":"search issues with counts: wisp dependency probe: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/search_counts.go","lineNumber":16,"sourceCode":"package issueops\n\nimport (\n\t\"context\"\n\t\"database/sql\"\n\t\"fmt\"\n\t\"sort\"\n\n\t\"github.com/steveyegge/beads/internal/storage/sqlbuild\"\n\t\"github.com/steveyegge/beads/internal/types\"\n)\n\nfunc SearchIssuesWithCountsInTx(ctx context.Context, tx *sql.Tx, query string, filter types.IssueFilter) ([]*types.IssueWithCounts, error) {\n\twispDepsExist, err := optionalTableExistsInTx(ctx, tx, \"wisp_dependencies\")\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"search issues with counts: wisp dependency probe: %w\", err)\n\t}\n\n\tif filter.Ephemeral != nil && *filter.Ephemeral {\n\t\tempty, probeErr := wispsTableEmptyOrMissingInTx(ctx, tx)\n\t\tif probeErr != nil {\n\t\t\treturn nil, fmt.Errorf(\"search issues with counts: ephemeral wisp probe: %w\", probeErr)\n\t\t}\n\t\tif !empty && wispDepsExist {\n\t\t\twisps, err := runFilterSearchQueryInTx(ctx, tx, query, filter, WispsFilterTables, true)\n\t\t\tif err != nil && !missingOptionalWispTable(err) {\n\t\t\t\treturn nil, err\n\t\t\t}\n\t\t\tif len(wisps) > 0 {\n\t\t\t\treturn finishSearchIssuesWithCounts(wisps, filter)\n\t\t\t}\n\t\t}\n\t\t// Fall through: the wisps tier is missing/empty or matched no rows.\n\t\t// Mirror SearchIssuesInTx / CountIssuesInTx so count-projection searches","sourceCodeStart":1,"sourceCodeEnd":34,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/search_counts.go#L1-L34","documentation":"SearchIssuesWithCountsInTx wraps a failure of the optionalTableExistsInTx probe for the wisp_dependencies table. Before searching with counts, the function checks whether this optional table exists so it can decide whether to merge ephemeral wisps; if the probe query itself fails, the whole search aborts with this wrapper.","triggerScenarios":"Calling SearchIssuesWithCountsInTx (bd search --counts path) where the schema-introspection query (e.g. querying sqlite_master / information_schema) errors — locked DB, ctx cancelled, corrupted catalog, or driver failure.","commonSituations":"Corrupted or locked SQLite file; Dolt server connection failure during introspection; context deadline hit before the first real query; unusual DB created without the expected catalog access.","solutions":["Unwrap the cause: it is a metadata-probe SQL failure, not a missing-table condition (missing is handled, failing is not)","Check DB file integrity and locks (bd doctor; lsof on the .db file)","Retry on a fresh connection if the connection was broken","Raise the context timeout if the probe was cancelled by a deadline","Run schema validation/repair; restore from backup if the catalog is corrupt"],"exampleFix":"// before: 1s deadline killed the table-existence probe\nctx, cancel := context.WithTimeout(ctx, time.Second)\n// after: allow the probe + search to complete\nctx, cancel := context.WithTimeout(ctx, 30*time.Second)\ndefer cancel()\niwcs, err := issueops.SearchIssuesWithCountsInTx(ctx, tx, q, filter)","handlingStrategy":"try-catch","validationCode":"// verify DB accessibility before count searches\nif err := tx.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"db unreachable for count search: %w\", err)\n}","typeGuard":"func isWispDepProbeErr(err error) bool {\n    return err != nil && strings.Contains(err.Error(),\n        \"search issues with counts: wisp dependency probe: \")\n}","tryCatchPattern":"res, err := issueops.SearchIssuesWithCountsInTx(ctx, tx, q, filter)\nif err != nil && isWispDepProbeErr(err) {\n    if errors.Is(err, context.DeadlineExceeded) {\n        ctx, cancel = context.WithTimeout(context.Background(), 30*time.Second)\n        defer cancel()\n        res, err = issueops.SearchIssuesWithCountsInTx(ctx, tx, q, filter)\n    }\n    if err != nil { return err }\n}","preventionTips":["Run bd doctor to verify DB/catalog health before count searches","Avoid running searches while another process holds an exclusive lock","Keep context deadlines realistic for remote databases","Retry once on transient probe failures"],"tags":["database","sql","schema-probe","search-counts"],"backgroundTag":"sql-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}