gastownhall/beads · error
count events: %w
Error message
count events: %w
What it means
DeleteResolvedSetInTx aborts when the SELECT COUNT over the "events" table for regular issue IDs fails. The error wraps the driver error from CountRowsForIssueIDsInTx; the count populates the events figure of the dry-run delete result.
Source
Thrown at internal/storage/issueops/delete.go:231
return nil, fmt.Errorf("count dependencies: %w", err)
}
wispDepsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_dependencies", set.WispIDs)
if err != nil {
return nil, fmt.Errorf("count wisp dependencies: %w", err)
}
depsCount += wispDepsCount
if labelsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "labels", set.RegularIDs); err != nil {
return nil, fmt.Errorf("count labels: %w", err)
}
wispLabelsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_labels", set.WispIDs)
if err != nil {
return nil, fmt.Errorf("count wisp labels: %w", err)
}
labelsCount += wispLabelsCount
if eventsCount, err = CountRowsForIssueIDsInTx(ctx, tx, "events", set.RegularIDs); err != nil {
return nil, fmt.Errorf("count events: %w", err)
}
wispEventsCount, err := CountRowsForIssueIDsInTx(ctx, tx, "wisp_events", set.WispIDs)
if err != nil {
return nil, fmt.Errorf("count wisp events: %w", err)
}
eventsCount += wispEventsCount
for i := 0; i < len(set.All); i += deleteBatchSize {
end := i + deleteBatchSize
if end > len(set.All) {
end = len(set.All)
}
batch := set.All[i:end]
batchInClause, batchArgs := buildSQLInClause(batch)
for _, depTable := range []string{"dependencies", "wisp_dependencies"} {
rows, err := tx.QueryContext(ctx,
fmt.Sprintf(`SELECT issue_id FROM %s WHERE %s`, depTable, depTargetIn("", batchInClause)),View on GitHub (pinned to 71377f2769)
Solutions
- Unwrap the error for the underlying cause (timeout vs connection vs schema).
- Retry the delete; transient lock/timeout failures usually clear.
- Raise the context timeout for deletes touching many issues with many events.
- Verify the events table exists and is healthy (e.g. via bd doctor).
Example fix
// before
res, err := store.DeleteInTx(ctx, tx, ids)
if err != nil {
log.Fatal(err)
}
// after
res, err := store.DeleteInTx(ctx, tx, ids)
if err != nil {
log.Printf("delete failed: %v", err)
if isTransient(err) {
res, err = store.DeleteInTx(ctx, tx, ids) // retry
}
} Defensive patterns
Strategy: retry
Validate before calling
var n int
err := db.QueryRowContext(ctx, `SELECT COUNT(*) FROM events LIMIT 1`).Scan(&n)
if err != nil {
return fmt.Errorf("events table unreadable before delete: %w", err)
} Try / catch
res, err := store.DeleteIssuesInTx(ctx, tx, ids)
if err != nil {
if errors.Is(err, context.DeadlineExceeded) {
ctx, cancel = context.WithTimeout(context.Background(), longerTimeout)
defer cancel()
res, err = store.DeleteIssuesInTx(ctx, tx, ids)
}
} Prevention
- Size context timeouts for the events-table volume of the issues being deleted.
- Monitor Dolt server health for query kills/timeouts.
- Split very large deletes into smaller batches.
When it happens
Trigger: Calling DeleteIssuesInTx/DeleteInTx when events is missing/unreadable, the transaction connection dropped after the label counts, or ctx was cancelled before this step.
Common situations: Very large events tables causing count timeouts; connection reset by Dolt server; lock contention with concurrent writers on events.
Related errors
- count wisp dependencies: %w
- count labels: %w
- count wisp labels: %w
- count wisp events: %w
- count inbound dependencies from %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/cc46963b235a126c.
Report an issue: GitHub.