gastownhall/beads · error
search %s: hydrate: %w
Error message
search %s: hydrate: %w
What it means
Raised when hydrateIssues fails after the core search rows were fetched successfully. Hydration fetches labels (and optionally dependency records) for the page of issues from their side tables; any error there is wrapped as "search <table>: hydrate: <err>". The search itself worked, but assembling full Issue objects failed.
Source
Thrown at internal/storage/domain/db/issue_search.go:289
if seen[issue.ID] {
continue
}
seen[issue.ID] = true
issues = append(issues, issue)
}
_ = rows.Close()
if err := rows.Err(); err != nil {
return domain.SearchPage{}, fmt.Errorf("search %s: rows: %w", tables.Main, err)
}
sortRowsGoSide(issues, func(i *types.Issue) string { return i.ID }, filter.SortBy, filter.SortDesc)
items, hasMore, err := finishWindow(issues, window)
if err != nil {
return domain.SearchPage{}, err
}
if err := r.hydrateIssues(ctx, items, tables, filter.IncludeDependencies, filter.SkipLabels); err != nil {
return domain.SearchPage{}, fmt.Errorf("search %s: hydrate: %w", tables.Main, err)
}
return domain.SearchPage{Items: items, HasMore: hasMore}, nil
}
func (r *issueSQLRepositoryImpl) scanFilterIDs(ctx context.Context, selectKw, fromSQL, whereSQL string, args []any, filter types.IssueFilter, tables filterTables) ([]string, bool, error) {
orderBy := orderBySQL(filter.SortBy, filter.SortDesc, tables.Main)
window := searchWindowForFilter(filter)
//nolint:gosec // G201: SQL fragments from fixed table names and parameterized filters.
idQuery := fmt.Sprintf(`%s%s.id FROM %s %s %s %s`,
selectKw, tables.Main, fromSQL, whereSQL, orderBy, window.sql)
rows, err := r.runner.QueryContext(ctx, idQuery, args...)
if err != nil {
return nil, false, fmt.Errorf("search %s (id scan): %w", tables.Main, err)
}
defer func() { _ = rows.Close() }()
View on GitHub (pinned to 71377f2769)
Solutions
- Unwrap to see which sub-fetch (labels vs dependencies) failed and why.
- Run `bd doctor` and migrations to ensure labels/dependencies tables exist and match the schema.
- Clear DB locks by stopping other bd processes, then retry the search.
- If a wisp side table is legitimately absent, set SkipWisps / Ephemeral filters to search the issues plane only.
Example fix
// before
filter := types.IssueFilter{} // hits wisps plane, missing wisp_labels table
// after
filter := types.IssueFilter{SkipWisps: true} // search issues plane only Defensive patterns
Strategy: validation
Validate before calling
// confirm side tables exist before dependency-inclusive or wisp searches
if err := bd.CheckTables(dbPath, "issues", "labels", "dependencies"); err != nil {
return fmt.Errorf("run `bd migrate`: %w", err)
} Type guard
func isHydrateError(err error) bool {
return err != nil && strings.Contains(err.Error(), ": hydrate: ")
} Try / catch
page, err := store.Search(ctx, q, filter)
if err != nil && isHydrateError(err) {
if name, ok := dberrors.MissingTableName(err); ok {
// fall back to a plain search without hydration-dependent filters
filter.IncludeDependencies = false
filter.SkipWisps = true
page, err = store.Search(ctx, q, filter)
}
} Prevention
- Run migrations whenever bd adds new side tables.
- Set SkipWisps when working with databases that intentionally lack wisp tables.
- Avoid concurrent writers that lock side tables during searches.
- Validate label/dependency rows after external edits.
When it happens
Trigger: searchTable succeeds on the main query but getLabelsFromTable or getDependencyRecordsFromTable fails for the hydrated IDs: labels/dependencies/wisp_labels table missing, locked DB, or a mid-hydration connection loss.
Common situations: Older database missing the labels or dependencies table; corrupt side tables after a manual edit; concurrent bd process holding a write lock so secondary reads stall/timeout; ephemeral wisp searches against a DB missing optional wisp side tables (though those are usually tolerated as missing-optional).
Related errors
- descendants: hydrate issues: %w
- hydrate labels: %w
- hydrate dependencies: %w
- hydrate ready row %s: dependency records: %w
- hydrate ready row %s: dependency records: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/db98774721221102.
Report an issue: GitHub.