gastownhall/beads · error
search count %s: %w
Error message
search count %s: %w
What it means
Generic wrapper in scanCountsQuery for QueryContext failures of a counts mega-query; %s is the main table name of the filterTables set (issues, wisps, dependencies...). Called from both fetchCountsByIDs and runSearchQuery, it marks which table family's counts query failed at the engine.
Source
Thrown at internal/storage/domain/db/issue_search_counts.go:183
if len(whereClauses) > 0 {
whereSQL = "WHERE " + strings.Join(whereClauses, " AND ")
}
orderBy := orderBySQL(filter.SortBy, filter.SortDesc, "i")
return r.runSearchQuery(ctx, tables, whereSQL, orderBy, searchWindowForFilter(filter).sql, args, includeWispReverseDeps, hydrationFor(filter))
}
//nolint:gosec // G201: SQL fragments are built from hardcoded table names and parameterized filters.
func (r *issueSQLRepositoryImpl) runSearchQuery(ctx context.Context, tables filterTables, whereSQL, orderBySQL, limitSQL string, args []any, includeWispReverseDeps bool, hyd sqlbuild.CountsHydration) ([]*types.IssueWithCounts, error) {
searchSQL, _ := sqlbuild.SearchCountsSQL(tables, nil, whereSQL, orderBySQL, limitSQL, includeWispReverseDeps, hyd)
return r.scanCountsQuery(ctx, tables, searchSQL, args, hyd)
}
// scanCountsQuery runs a prebuilt counts mega-query and hydrates each row,
// deduping by issue ID (mirrors issueops.scanCountsRowsInTx).
func (r *issueSQLRepositoryImpl) scanCountsQuery(ctx context.Context, tables filterTables, query string, args []any, hyd sqlbuild.CountsHydration) ([]*types.IssueWithCounts, error) {
rows, err := r.runner.QueryContext(ctx, query, args...)
if err != nil {
return nil, fmt.Errorf("search count %s: %w", tables.Main, err)
}
defer func() { _ = rows.Close() }()
var out []*types.IssueWithCounts
seen := make(map[string]bool)
for rows.Next() {
iwc, scanErr := scanReadyWorkRowWithCounts(rows, hyd)
if scanErr != nil {
return nil, scanErr
}
if iwc == nil || iwc.Issue == nil {
continue
}
if seen[iwc.Issue.ID] {
continue
}
seen[iwc.Issue.ID] = true
out = append(out, iwc)View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped driver error message for the concrete cause
- Run bd migrations / bd doctor to ensure all counts-related tables exist
- Reduce hydration breadth (SkipLabels/SkipCounts/Lite) or page size
- Increase context timeout; retry transient connection errors
Example fix
// before ctx, cancel := context.WithTimeout(ctx, 2*time.Second) // after ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
Defensive patterns
Strategy: retry
Validate before calling
for _, t := range []string{"issues", "dependencies", "labels", "wisp_dependencies"} {
if err := tableExists(ctx, db, t); err != nil {
return fmt.Errorf("missing table %s: %w", t, err)
}
} Try / catch
items, err := store.Search(ctx, q, filter)
if err != nil {
var derr *driverError
if errors.As(err, &derr) && derr.Transient() {
items, err = store.Search(ctx, q, filter)
}
} Prevention
- Run schema checks (bd doctor) before heavy counts queries
- Cap ID batch sizes to stay under parameter limits
- Use SkipLabels/SkipCounts/Lite for constrained environments
- Apply context deadlines with retry on deadline-exceeded
When it happens
Trigger: QueryContext fails on any counts mega-query — unknown table/column, engine syntax error, too many bound parameters, connection loss, or context deadline exceeded.
Common situations: Stale schema missing dependencies/wisp tables (outside the tolerated optional paths), very large ID chunks stressing parameter limits, remote Dolt connection drops, or timeouts on wide aggregate queries.
Related errors
- failed to begin transaction: %w
- failed to recompute is_blocked: %w
- failed to commit is_blocked repairs: %w
- %s: %w
- failed to query orphaned dependencies: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6cf2aec163d2be27.
Report an issue: GitHub.