gastownhall/beads · error
search %s: %w
Error message
search %s: %w
What it means
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.
Source
Thrown at internal/storage/domain/db/issue_search.go:260
return domain.SearchPage{}, nil
}
byID, err := r.fetchIssuesByIDs(ctx, ids, tables, filter)
if err != nil {
return domain.SearchPage{}, fmt.Errorf("search %s (hydrate): %w", tables.Main, err)
}
return domain.SearchPage{Items: orderByIDs(ids, byID), HasMore: hasMore}, nil
}
orderBy := orderBySQL(filter.SortBy, filter.SortDesc, "")
window := searchWindowForFilter(filter)
//nolint:gosec // G201: SQL fragments from fixed table names and parameterized filters.
querySQL := fmt.Sprintf(`%s%s FROM %s %s %s %s %s`,
selectKw, issueSelectColumns, plan.FromSQL, sqlbuild.LeaseJoin(tables.Main), whereSQL, orderBy, window.sql)
rows, err := r.runner.QueryContext(ctx, querySQL, args...)
if err != nil {
return domain.SearchPage{}, fmt.Errorf("search %s: %w", tables.Main, err)
}
var issues []*types.Issue
seen := make(map[string]bool)
for rows.Next() {
issue, scanErr := scanIssue(rows)
if scanErr != nil {
_ = rows.Close()
return domain.SearchPage{}, fmt.Errorf("search %s: scan: %w", tables.Main, scanErr)
}
if seen[issue.ID] {
continue
}
seen[issue.ID] = true
issues = append(issues, issue)
}
_ = rows.Close()
if err := rows.Err(); err != nil {View on GitHub (pinned to 71377f2769)
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.
Example fix
// before
page, err := store.Search(ctx, query, filter) // fails: database is locked
// after
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := bd.Doctor(ctx, dbPath); err != nil { /* repair DB first */ }
page, err := store.Search(ctx, query, filter) Defensive patterns
Strategy: try-catch
Validate before calling
if _, err := os.Stat(dbPath); err != nil { return fmt.Errorf("database missing: %w", err) }
if err := bd.Doctor(ctx, dbPath); err != nil { return err } Type guard
func isSearchQueryError(err error) bool {
return err != nil && strings.Contains(err.Error(), "search ")
} Try / catch
page, err := store.Search(ctx, q, filter)
if err != nil {
var root error
for unwrapped := err; unwrapped != nil; unwrapped = errors.Unwrap(unwrapped) {
root = unwrapped
}
if dberrors.IsLocked(root) || errors.Is(root, context.DeadlineExceeded) {
// retry with backoff
}
return fmt.Errorf("search failed: %w", err)
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- search issues: %w
- search %s (id scan): %w
- get dependents from %s: %w
- count edges in %s: %w
- check issue existence in %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/c84467e361c8937d.
Report an issue: GitHub.