gastownhall/beads · error

db: EventsSQLRepository.CountAllForIDs: %w

Error message

db: EventsSQLRepository.CountAllForIDs: %w

What it means

Wraps failures from CountRowsForIssueIDsInTx when counting event rows for issue IDs in events or wisp_events. Like other wisp paths, a missing wisp table returns 0,nil, so this error indicates a real count failure on an existing table.

Source

Thrown at internal/storage/domain/db/events.go:87

		total += int(n)
	}
	return total, nil
}

func (r *eventsSQLRepositoryImpl) CountAllForIDs(ctx context.Context, ids []string, opts domain.RecordEventOpts) (int, error) {
	if len(ids) == 0 {
		return 0, nil
	}
	table := "events"
	if opts.UseWispsTable {
		table = "wisp_events"
	}
	count, err := issueops.CountRowsForIssueIDsInTx(ctx, r.runner, table, ids)
	if err != nil {
		if opts.UseWispsTable && dberrors.IsTableNotExist(err) {
			return 0, nil
		}
		return 0, fmt.Errorf("db: EventsSQLRepository.CountAllForIDs: %w", err)
	}
	return count, nil
}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Inspect the wrapped driver error (context deadline, lock timeout, unknown table)
  2. Run migrations if the non-wisp events table is missing
  3. Increase the context timeout or scope IDs to smaller batches
  4. Check for long-running transactions blocking the count

Example fix

// before
count, err := repo.CountAllForIDs(ctx, ids, opts) // ctx has 1s timeout
// after
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
count, err := repo.CountAllForIDs(ctx, ids, opts)
Defensive patterns

Strategy: try-catch

Validate before calling

if len(ids) == 0 { return 0, nil }
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()

Type guard

func isTransientCountErr(err error) bool {
    return errors.Is(err, context.DeadlineExceeded) || errors.Is(err, context.Canceled) || isLockTimeoutErr(err)
}

Try / catch

count, err := repo.CountAllForIDs(ctx, ids, opts)
if err != nil {
    if isTransientCountErr(err) { return retryCount(ctx, ids, opts) }
    return fmt.Errorf("count events: %w", err)
}

Prevention

When it happens

Trigger: Calling CountAllForIDs when the SELECT COUNT fails: bad table name from opts, connection error, context cancellation, or malformed ID list causing SQL errors.

Common situations: Context deadline exceeded during a large count; events table locked by heavy write traffic; typo or drift in table configuration leading to a non-wisp missing table.

Related errors


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/192dc4cf774635b6. Report an issue: GitHub.