gastownhall/beads · error
wisp id set: rows: %w
Error message
wisp id set: rows: %w
What it means
WispIDSetInTx issues a batched `SELECT id FROM wisps WHERE id IN (...)` and calls rows.Err() after draining each batch. This error wraps a rows-iteration failure (connection drop, context cancellation mid-scan, driver decode error) after rows were successfully opened but the iteration itself reported an error via rows.Err(). It means the wisp-ID set could not be built reliably, so the caller must not trust a partial partition.
Source
Thrown at internal/storage/issueops/wisp_routing.go:104
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 {
return nil, fmt.Errorf("wisp id set: %w", err)
}
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
_ = rows.Close()
return nil, fmt.Errorf("wisp id set: scan: %w", err)
}
set[id] = struct{}{}
}
_ = rows.Close()
if err := rows.Err(); err != nil {
return nil, fmt.Errorf("wisp id set: rows: %w", err)
}
}
return set, nil
}
// partitionByWispSet splits ids into (wispIDs, permIDs) using the provided
// wisp-id set. If wispSet is nil the caller must populate it first via
// WispIDSetInTx; this helper does no I/O.
func partitionByWispSet(ids []string, wispSet map[string]struct{}) (wispIDs, permIDs []string) {
for _, id := range ids {
if _, isWisp := wispSet[id]; isWisp {
wispIDs = append(wispIDs, id)
} else {
permIDs = append(permIDs, id)
}
}
return wispIDs, permIDs
}View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped driver error to determine root cause: network error → reconnect; context.DeadlineExceeded → raise the timeout or reduce the batch size
- Retry the operation with a fresh transaction — Dolt MVCC makes the set consistent per tx, so a clean retry is safe
- Verify connectivity to the Dolt server (bd dolt ping / connection settings) if errors are persistent
- Reduce queryBatchSize input volume so each IN-query chunk completes well inside the context deadline
Example fix
// before
set, err := issueops.WispIDSetInTx(ctx, tx, ids)
if err != nil { return err }
// after
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
set, err := issueops.WispIDSetInTx(ctx, tx, ids)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) { return retryWithFreshTx(ctx, ids) }
return fmt.Errorf("partition wisps: %w", err)
} Defensive patterns
Strategy: retry
Validate before calling
if len(ids) == 0 { return nil } // never triggers a query
if err := ctx.Err(); err != nil { return fmt.Errorf("context already done: %w", err) } Try / catch
set, err := issueops.WispIDSetInTx(ctx, tx, ids)
if err != nil {
var netErr net.Error
if errors.As(err, &netErr) || errors.Is(err, context.DeadlineExceeded) {
// retry with fresh tx and larger deadline
}
return err
} Prevention
- Size context deadlines for the batch volume, especially over WAN to remote Dolt
- Pass a non-cancelled context; avoid propagating short HTTP timeouts into storage calls
- Keep batches within queryBatchSize so each IN-query chunk is small
- Monitor connection stability to the Dolt server
When it happens
Trigger: Calling WispIDSetInTx (directly or via ReconcileChildCounters, DeleteInTx, GetIssuesByIDsInTx, ExecuteAddDependencies) when the underlying database connection fails or the context is cancelled while iterating result rows of the wisps-table IN query.
Common situations: Dolt server connection dropped mid-query (network blip to remote Dolt); caller's context deadline exceeded during a large batch partition (GH#3414 WAN-latency scenario); driver-level row decode failure after schema drift.
Related errors
- partition wisp ids: rows: %w
- db: ChildCounterSQLRepository.NextChildID: rows: %w
- db: CommentSQLRepository.CountsByIssueIDs: rows: %w
- db: CommentSQLRepository.ListByIssueIDs: rows: %w
- db: RawSQL Query: rows: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/6c26bda486d77b55.
Report an issue: GitHub.