gastownhall/beads · error
search issues with counts: wisp probe: %w
Error message
search issues with counts: wisp probe: %w
What it means
SearchIssuesWithCountsInTx wraps a failure of wispsTableEmptyOrMissingInTx on the default (non-ephemeral) path, after the durable issues query and unless filter.SkipWisps was set. The probe decides whether the wisps merge step is needed; if the probe query itself fails, the search aborts wrapped as 'wisp probe'.
Source
Thrown at internal/storage/issueops/search_counts.go:58
if err != nil {
return nil, err
}
return finishSearchIssuesWithCounts(out, filter)
}
out, err := runFilterSearchQueryInTx(ctx, tx, query, filter, IssuesFilterTables, wispDepsExist)
if err != nil {
return nil, err
}
// Skip wisps merge entirely when caller opts out (Q2: perf escape hatch).
if filter.SkipWisps {
return finishSearchIssuesWithCounts(out, filter)
}
empty, probeErr := wispsTableEmptyOrMissingInTx(ctx, tx)
if probeErr != nil {
return nil, fmt.Errorf("search issues with counts: wisp probe: %w", probeErr)
}
if empty {
return finishSearchIssuesWithCounts(out, filter)
}
if !wispDepsExist {
return finishSearchIssuesWithCounts(out, filter)
}
wisps, err := runFilterSearchQueryInTx(ctx, tx, query, filter, WispsFilterTables, true)
if err != nil {
if missingOptionalWispTable(err) {
return finishSearchIssuesWithCounts(out, filter)
}
return nil, err
}
if len(wisps) == 0 {
return finishSearchIssuesWithCounts(out, filter)
}View on GitHub (pinned to 71377f2769)
Solutions
- Unwrap the cause and address the driver-level failure (lock, connection, timeout)
- Set filter.SkipWisps = true if you only need durable issues and can skip the wisps merge (explicit perf escape hatch)
- Retry the search — probes are usually transient failures
- Raise the context timeout for remote/slow stores
- Run bd doctor to check DB integrity and table accessibility
Example fix
// before: durable-only consumer still paying for (and failing on) the wisp probe res, err := issueops.SearchIssuesWithCountsInTx(ctx, tx, q, filter) // after: caller does not need wisps filter.SkipWisps = true res, err := issueops.SearchIssuesWithCountsInTx(ctx, tx, q, filter)
Defensive patterns
Strategy: fallback
Validate before calling
// skip the wisp probe entirely when wisps are not needed
if !needEphemeral {
filter.SkipWisps = true
} Type guard
func isWispProbeErr(err error) bool {
return err != nil && strings.Contains(err.Error(),
"search issues with counts: wisp probe: ")
} Try / catch
res, err := issueops.SearchIssuesWithCountsInTx(ctx, tx, q, filter)
if err != nil && isWispProbeErr(err) {
// fall back to durable-issues-only results
filter.SkipWisps = true
res, err = issueops.SearchIssuesWithCountsInTx(ctx, tx, q, filter)
} Prevention
- Set SkipWisps whenever you only consume durable issues
- Keep short context deadlines off remote stores doing wisp merges
- Retry transient probe failures on a fresh transaction
- Run bd doctor if probe failures repeat
When it happens
Trigger: Calling SearchIssuesWithCountsInTx without SkipWisps where the wisps-table emptiness probe errors — lock contention, dropped connection, ctx cancellation, or a corrupted/inaccessible wisps table preventing even an existence/emptiness check.
Common situations: bd list/search --counts against a database where a crashed writer left the wisps table locked; remote Dolt server briefly unreachable; deadline exceeded on large remote stores.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- search issues with counts: ephemeral wisp probe: %w
- count open wisp children for %s: %w
- search issues with counts: wisp dependency probe: %w
- failed to begin transaction: %w
- failed to recompute is_blocked: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/73d28aa33811e049.
Report an issue: GitHub.