{"record":{"id":"b0398c91004d3a41","repo":"gastownhall/beads","slug":"search-s-id-scan-w","errorCode":null,"errorMessage":"search %s (id scan): %w","messagePattern":"search (.+?) \\(id scan\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/issue_search.go","lineNumber":304,"sourceCode":"\t}\n\n\tif err := r.hydrateIssues(ctx, items, tables, filter.IncludeDependencies, filter.SkipLabels); err != nil {\n\t\treturn domain.SearchPage{}, fmt.Errorf(\"search %s: hydrate: %w\", tables.Main, err)\n\t}\n\n\treturn domain.SearchPage{Items: items, HasMore: hasMore}, nil\n}\n\nfunc (r *issueSQLRepositoryImpl) scanFilterIDs(ctx context.Context, selectKw, fromSQL, whereSQL string, args []any, filter types.IssueFilter, tables filterTables) ([]string, bool, error) {\n\torderBy := orderBySQL(filter.SortBy, filter.SortDesc, tables.Main)\n\twindow := searchWindowForFilter(filter)\n\t//nolint:gosec // G201: SQL fragments from fixed table names and parameterized filters.\n\tidQuery := fmt.Sprintf(`%s%s.id FROM %s %s %s %s`,\n\t\tselectKw, tables.Main, fromSQL, whereSQL, orderBy, window.sql)\n\n\trows, err := r.runner.QueryContext(ctx, idQuery, args...)\n\tif err != nil {\n\t\treturn nil, false, fmt.Errorf(\"search %s (id scan): %w\", tables.Main, err)\n\t}\n\tdefer func() { _ = rows.Close() }()\n\n\tvar ids []string\n\tfor rows.Next() {\n\t\tvar id string\n\t\tif err := rows.Scan(&id); err != nil {\n\t\t\treturn nil, false, fmt.Errorf(\"search %s (id scan): scan: %w\", tables.Main, err)\n\t\t}\n\t\tids = append(ids, id)\n\t}\n\tif err := rows.Err(); err != nil {\n\t\treturn nil, false, fmt.Errorf(\"search %s (id scan): rows: %w\", tables.Main, err)\n\t}\n\n\tsortRowsGoSide(ids, func(id string) string { return id }, filter.SortBy, filter.SortDesc)\n\treturn finishWindow(ids, window)\n}","sourceCodeStart":286,"sourceCodeEnd":322,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/issue_search.go#L286-L322","documentation":"Raised when the ID-scan phase of searchTable (scanFilterIDs) fails to execute its query. This lighter query selects only table.id with the same FROM/WHERE/ORDER/window clauses; execution errors from the driver are wrapped as \"search <table> (id scan): <err>\". The ID-scan path is used for a subset of filters, so this error appears only on those code paths.","triggerScenarios":"Calling a search path that routes through scanFilterIDs when the main query against the issues/wisps table fails: missing table, locked DB, connection failure, or cancelled context — same class as the full-search query failure but from the id-only SQL.","commonSituations":"Database schema drift (table absent); DB file locked by another process; context deadline shorter than the query on large tables; remote Dolt server unreachable.","solutions":["Unwrap the error chain to identify the driver-level cause (no such table, locked, connection).","Run `bd doctor` to verify database integrity and schema; re-migrate if needed.","Release concurrent locks (close other bd sessions) and retry.","Extend the context deadline or add filters to shrink the scanned table."],"exampleFix":"// before\nctx, cancel := context.WithTimeout(ctx, 100*time.Millisecond) // too short for id scan\n// after\nctx, cancel := context.WithTimeout(ctx, 30*time.Second)","handlingStrategy":"try-catch","validationCode":"if _, err := os.Stat(dbPath); err != nil { return err }\nif err := ctx.Err(); err != nil { return err }","typeGuard":"func isIDScanError(err error) bool {\n\treturn err != nil && strings.Contains(err.Error(), \"(id scan)\")\n}","tryCatchPattern":"page, err := store.Search(ctx, q, filter)\nif err != nil && isIDScanError(err) {\n\tif dberrors.IsMissingTable(err) {\n\t\treturn fmt.Errorf(\"database out of date, run `bd migrate`: %w\", err)\n\t}\n\t// locked or transient: retry once\n}","preventionTips":["Keep schema migrations current with the bd binary version.","Use realistic context timeouts for filtered scans of large tables.","Serialize write access to the database across processes."],"tags":["database","sql","query-execution","id-scan"],"backgroundTag":"sql-query-execution-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}