gastownhall/beads · error
search union with counts (hydrate issues): %w
Error message
search union with counts (hydrate issues): %w
What it means
Wraps failures from fetchCountsByIDs when hydrating counts (labels, dependencies, etc.) for the issue IDs on the union page. The hydration uses the by-IDs counts mega-query with chunked IDs; failures here mean the follow-up hydration SQL failed, not the main search.
Source
Thrown at internal/storage/domain/db/issue_search_counts.go:103
args = append(args, wArgs...)
rows, err := r.runner.QueryContext(ctx, unionSQL, args...)
if err != nil {
return domain.SearchCountsPage{}, fmt.Errorf("search union with counts: %w", err)
}
page, err := scanIDSrcPage(rows)
if err != nil {
return domain.SearchCountsPage{}, fmt.Errorf("search union with counts: %w", err)
}
page.sortGoSide(filter.SortBy, filter.SortDesc)
hasMore, err := page.finishWindow(window)
if err != nil {
return domain.SearchCountsPage{}, err
}
issuesByID, err := r.fetchCountsByIDs(ctx, page.issueIDs, issuesFilterTables, wispDepsExist, hydrationFor(filter))
if err != nil {
return domain.SearchCountsPage{}, fmt.Errorf("search union with counts (hydrate issues): %w", err)
}
wispsByID, err := r.fetchCountsByIDs(ctx, page.wispIDs, wispsFilterTables, true, hydrationFor(filter))
if err != nil && !missingOptionalWispTable(err) {
return domain.SearchCountsPage{}, fmt.Errorf("search union with counts (hydrate wisps): %w", err)
}
out := reassembleBySrc(page.ordered, issuesByID, wispsByID)
return domain.SearchCountsPage{Items: out, HasMore: hasMore}, nil
}
// hydrationFor reads the hydration opt-outs off a search filter, matching the
// store-backed path's helper of the same name (internal/storage/issueops).
// Both bodies must read the same fields off the same filter or a caller that
// set one would get different columns from the two backends.
func hydrationFor(filter types.IssueFilter) sqlbuild.CountsHydration {
return sqlbuild.CountsHydration{SkipLabels: filter.SkipLabels, SkipCounts: filter.SkipCounts, Lite: filter.Lite}
}
View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the inner 'search count issues' error for the engine message
- Reduce page size / skip hydration via filter.SkipCounts or filter.Lite to shrink the mega-query
- Verify dependencies/labels tables exist and schema matches
- Retry on transient connection errors
Example fix
// before
filter := types.IssueFilter{...}
// after
filter.SkipCounts = true // or filter.Lite = true to lighten hydration Defensive patterns
Strategy: fallback
Validate before calling
if page.ItemCount > largePageThreshold {
filter.Lite = true // shrink hydration before calling
} Try / catch
page, err := store.SearchWithCounts(ctx, q, filter)
if err != nil && strings.Contains(err.Error(), "hydrate issues") {
filter.SkipCounts = true
page, err = store.SearchWithCounts(ctx, q, filter) // degrade gracefully
} Prevention
- Offer Lite/SkipCounts modes for big pages
- Set generous hydration timeouts
- Keep dependency/label table schemas migrated
- Chunk hydration by IDs (as the library does) and monitor chunk failures
When it happens
Trigger: After the union page is built, fetchCountsByIDs for page.issueIDs fails — engine error in the counts mega-query, context cancellation, or chunked placeholder issues.
Common situations: Timeouts during hydration of large pages, schema issues in dependency/label tables, or DB connection drops between the search and hydration queries.
Related errors
- search %s: %w
- search issues: %w
- search %s: %w
- search union with counts (issues): %w
- search union with counts (wisps): %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/f11a9492e0bfa96e.
Report an issue: GitHub.