gastownhall/beads · error

journal: advance seq counter: %w

Error message

journal: advance seq counter: %w

What it means

nextEventSeq advances the monolithic sequence row in bd_events_seq (UPDATE ... SET next_seq = next_seq + 1 WHERE id = 0) to allocate a journal sequence number for a new event row. This error wraps a failure of that UPDATE inside the caller's transaction and is the error carried up from insertEventRow. It means the journal write aborted before an event could even get a seq number.

Source

Thrown at internal/storage/issueops/journal.go:519

// nextEventSeq allocates the next journal sequence number from the single-row
// bd_events_seq counter, INSIDE the caller's transaction. Incrementing the
// shared counter row is what serializes seq assignment: two transactions that
// both allocate a seq contend on the one row, so only one commit order survives.
// The value becomes the journal row's seq, yielding gapless, commit-ordered seqs
// (a rolled-back transaction rolls back its increment, burning no seq). The
// counter persists across restart and prune never touches it, so seq never
// resets. The seed row is created by migration 0064 / ignored 0022; the
// self-heal below re-creates it at the journal's high-water mark if it is ever
// missing, so a re-seed can never collide with an existing seq. A counter that
// is PRESENT but stale cannot be detected here without a per-emit MAX(seq)
// read, so insertEventRow heals that case reactively off the duplicate-key
// failure instead — see there.
func nextEventSeq(ctx context.Context, tx DBTX) (int64, error) {
	advance := func() (int64, error) {
		res, err := tx.ExecContext(ctx, "UPDATE bd_events_seq SET next_seq = next_seq + 1 WHERE id = 0")
		if err != nil {
			return 0, fmt.Errorf("journal: advance seq counter: %w", err)
		}
		return res.RowsAffected()
	}
	n, err := advance()
	if err != nil {
		return 0, err
	}
	if n == 0 {
		// The counter row is missing entirely: seed it at the journal's
		// high-water mark, so the re-seed can never collide with an existing seq.
		if err := healEventSeqCounter(ctx, tx); err != nil {
			return 0, err
		}
		if _, err := advance(); err != nil {
			return 0, err
		}
	}
	var seq int64

View on GitHub (pinned to 71377f2769)

Solutions

  1. Run the schema migration to ensure bd_events_seq exists (verify with SELECT next_seq FROM bd_events_seq WHERE id = 0).
  2. Retry the operation: the wrapped error is often a transient deadlock/lock-timeout on the single seq row; re-run the whole transaction.
  3. Check database connectivity and server logs for connection drops during the transaction.
  4. Confirm the DB user has UPDATE privilege on bd_events_seq.

Example fix

// before
err := store.CreateIssue(ctx, issue) // fails: journal: advance seq counter: deadlock
// after
err := retry.OnDeadline(func() error { return store.CreateIssue(ctx, issue) }) // retry whole tx on transient lock errors; ensure migrations ran first
Defensive patterns

Strategy: retry

Validate before calling

var n int64
if err := db.QueryRow("SELECT next_seq FROM bd_events_seq WHERE id = 0").Scan(&n); err != nil {
    return fmt.Errorf("journal schema not migrated: %w", err)
}

Try / catch

err := retry.Do(func() error {
    _, err := store.CreateIssue(ctx, issue)
    if err != nil && strings.Contains(err.Error(), "journal: advance seq counter") && isTransient(err) {
        return retry.RetryableError(err)
    }
    return err
})

Prevention

When it happens

Trigger: Calling any event-emitting storage operation (e.g. via insertEventRow) when the UPDATE on bd_events_seq fails: the transaction is already broken (deadlock, lock wait timeout), the table is missing (schema not migrated, table dropped), the connection was lost mid-transaction, or a driver-level SQL syntax/permission failure occurs.

Common situations: Concurrent writers deadlocking on the single seq row; an old database opened by a newer binary before migration added bd_events_seq; connection killed by network blip or server timeout during a long transaction; insufficient privileges for the app DB user.

Related errors


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