gastownhall/beads · error
wisp id set: probe: %w
Error message
wisp id set: probe: %w
What it means
WispIDSetInTx first probes whether the wisps table is empty or missing before batch-querying ids; this error wraps a failure of that probe itself. A missing table is treated as empty (not an error), so reaching this error means a real probe failure: connection problems, permission denied, or an unexpected SQL error from the existence check.
Source
Thrown at internal/storage/issueops/wisp_routing.go:73
// WispIDSetInTx returns the subset of ids that are currently-active wisps
// within the tx. The set is consistent for the tx's lifetime (Dolt MVCC).
// Intended for hot-path partitioning where a batch of IDs must be split
// into wisps vs permanents; one scoped query amortized over the batch
// replaces N per-ID IsActiveWispInTx calls without paying for a full
// wisps-table scan when callers have a small batch against a large
// wisps table.
//
// Returns an empty set when ids is empty; never issues a query.
//
//nolint:gosec // G201: query uses placeholder-only interpolation
func WispIDSetInTx(ctx context.Context, tx DBTX, ids []string) (map[string]struct{}, error) {
set := make(map[string]struct{})
if len(ids) == 0 {
return set, nil
}
if empty, err := wispsTableEmptyOrMissingInTx(ctx, tx); err != nil {
return nil, fmt.Errorf("wisp id set: probe: %w", err)
} else if empty {
return set, nil
}
for start := 0; start < len(ids); start += queryBatchSize {
end := start + queryBatchSize
if end > len(ids) {
end = len(ids)
}
batch := ids[start:end]
placeholders := make([]string, len(batch))
args := make([]any, len(batch))
for i, id := range batch {
placeholders[i] = "?"
args[i] = id
}
q := fmt.Sprintf("SELECT id FROM wisps WHERE id IN (%s)", strings.Join(placeholders, ","))
rows, err := tx.QueryContext(ctx, q, args...)
if err != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped probe error to distinguish permissions vs connection vs SQL incompatibility.
- Grant the database user SELECT privileges on the wisps table (or create it via migration).
- Verify the backend supports the probe query (MySQL/Dolt-compatible driver required).
- Retry after the connection is restored.
Example fix
// before: restricted user GRANT SELECT ON db.issues TO 'beads'@'%'; // after GRANT SELECT ON db.* TO 'beads'@'%';
Defensive patterns
Strategy: try-catch
Validate before calling
// verify the user can read the wisps table
var one int
err := db.QueryRow("SELECT 1 FROM wisps LIMIT 1").Scan(&one)
if err != nil {
var myErr *mysql.MySQLError
if errors.As(err, &myErr) && (myErr.Number == 1142 || myErr.Number == 1146) {
return fmt.Errorf("wisps table inaccessible/missing: grant SELECT or run migration")
}
} Try / catch
if err != nil {
var myErr *mysql.MySQLError
if errors.As(err, &myErr) && myErr.Number == 1142 {
return fmt.Errorf("insufficient privileges on wisps table: %w", err)
}
return err
} Prevention
- Grant the beads DB user broad SELECT on the schema, not per-table.
- Ensure the backend is MySQL/Dolt-compatible (probe SQL dependency).
- Run migrations so the wisps table exists with current code.
- Ping the database before routing-heavy operations.
When it happens
Trigger: Calling any of WispIDSetInTx's callers (ReconcileChildCounters, DeleteInTx, GetIssuesByIDsInTx, ExecuteAddDependencies) when the wisps-table emptiness probe fails due to a broken connection, insufficient privileges, or probe-query incompatibility with the backend.
Common situations: User lacks SELECT/SHOW permission on the wisps table; connection dropped; non-MySQL backend where the probe's SQL (information_schema lookups or similar) does not exist.
Related errors
- wisp id set: %w
- wisp id set: scan: %w
- wisp id set: rows: %w
- partition wisp ids: probe: %w
- partition wisp ids: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/4f18835f16b712d3.
Report an issue: GitHub.