{"record":{"id":"c84467e361c8937d","repo":"gastownhall/beads","slug":"search-s-w","errorCode":null,"errorMessage":"search %s: %w","messagePattern":"search (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/issue_search.go","lineNumber":260,"sourceCode":"\t\t\treturn domain.SearchPage{}, nil\n\t\t}\n\t\tbyID, err := r.fetchIssuesByIDs(ctx, ids, tables, filter)\n\t\tif err != nil {\n\t\t\treturn domain.SearchPage{}, fmt.Errorf(\"search %s (hydrate): %w\", tables.Main, err)\n\t\t}\n\t\treturn domain.SearchPage{Items: orderByIDs(ids, byID), HasMore: hasMore}, nil\n\t}\n\n\torderBy := orderBySQL(filter.SortBy, filter.SortDesc, \"\")\n\twindow := searchWindowForFilter(filter)\n\n\t//nolint:gosec // G201: SQL fragments from fixed table names and parameterized filters.\n\tquerySQL := fmt.Sprintf(`%s%s FROM %s %s %s %s %s`,\n\t\tselectKw, issueSelectColumns, plan.FromSQL, sqlbuild.LeaseJoin(tables.Main), whereSQL, orderBy, window.sql)\n\n\trows, err := r.runner.QueryContext(ctx, querySQL, args...)\n\tif err != nil {\n\t\treturn domain.SearchPage{}, fmt.Errorf(\"search %s: %w\", tables.Main, err)\n\t}\n\n\tvar issues []*types.Issue\n\tseen := make(map[string]bool)\n\tfor rows.Next() {\n\t\tissue, scanErr := scanIssue(rows)\n\t\tif scanErr != nil {\n\t\t\t_ = rows.Close()\n\t\t\treturn domain.SearchPage{}, fmt.Errorf(\"search %s: scan: %w\", tables.Main, scanErr)\n\t\t}\n\t\tif seen[issue.ID] {\n\t\t\tcontinue\n\t\t}\n\t\tseen[issue.ID] = true\n\t\tissues = append(issues, issue)\n\t}\n\t_ = rows.Close()\n\tif err := rows.Err(); err != nil {","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/issue_search.go#L242-L278","documentation":"This error wraps a failure from the underlying SQL driver when executing the issue/wisp search query via runner.QueryContext. The beads storage layer parameterizes all filters and only interpolates fixed table names, so any error here originates from the database engine itself (syntax, connection, schema) and is reported as \"search <table>: <driver error>\". It propagates up through SearchAcrossIssuesAndWisps to the caller's IssueFilter-based search API.","triggerScenarios":"Calling Search / SearchAcrossIssuesAndWisps when the database rejects the generated search SQL: locked or unreadable SQLite/Dolt database, missing issues or wisps table, driver-level connection loss mid-query, or a context cancelled/expired before the query completes.","commonSituations":"Corrupt or migrated-away .beads database file; running a newer bd binary against an older DB schema lacking a table the search expects; WAL lock contention from a concurrent bd process; disk-full or permission errors on the DB file; long-running search killed by context deadline in a daemon.","solutions":["Inspect the wrapped driver error (errors.Unwrap / %w chain) to identify the root cause (no such table, locked, I/O error).","Run `bd doctor` to validate database health and schema; re-migrate or rebuild the database if tables are missing.","Close other bd processes holding a lock on the database and retry.","Check disk space and file permissions on the .beads directory.","Ensure the context passed to Search has an adequate deadline, or pass context.Background() for interactive searches."],"exampleFix":"// before\npage, err := store.Search(ctx, query, filter) // fails: database is locked\n// after\nctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)\ndefer cancel()\nif err := bd.Doctor(ctx, dbPath); err != nil { /* repair DB first */ }\npage, err := store.Search(ctx, query, filter)","handlingStrategy":"try-catch","validationCode":"if _, err := os.Stat(dbPath); err != nil { return fmt.Errorf(\"database missing: %w\", err) }\nif err := bd.Doctor(ctx, dbPath); err != nil { return err }","typeGuard":"func isSearchQueryError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"search \")\n}","tryCatchPattern":"page, err := store.Search(ctx, q, filter)\nif err != nil {\n\tvar root error\n\tfor unwrapped := err; unwrapped != nil; unwrapped = errors.Unwrap(unwrapped) {\n\t\troot = unwrapped\n\t}\n\tif dberrors.IsLocked(root) || errors.Is(root, context.DeadlineExceeded) {\n\t\t// retry with backoff\n\t}\n\treturn fmt.Errorf(\"search failed: %w\", err)\n}","preventionTips":["Run `bd doctor` after upgrading bd or before batch operations.","Avoid hosting .beads databases on network filesystems.","Keep context deadlines generous for large searches.","Ensure only one bd process mutates the database at a time."],"tags":["database","sql","search","query-execution"],"backgroundTag":"sql-query-execution-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}