gastownhall/beads · error
record wake event for %s: %w
Error message
record wake event for %s: %w
What it means
Thrown when RecordFullEventInTable fails while journaling the deferred→open status-change event for a freshly woken issue. The row was already updated to 'open' in the same transaction, so this error leaves a woken bead without its status-change history entry; the whole transaction aborts via the returned error.
Source
Thrown at internal/storage/issueops/wake_defers.go:133
res, err := tx.ExecContext(ctx, fmt.Sprintf(`
UPDATE %s
SET status = 'open', defer_until = NULL, updated_at = ?, row_lock = ?
WHERE id = ? AND status = 'deferred' AND defer_until IS NOT NULL
AND defer_until <= UTC_TIMESTAMP()
`, table), now, freshRowLock(), id)
if err != nil {
return woken, fmt.Errorf("wake expired defer %s: %w", id, err)
}
n, err := res.RowsAffected()
if err != nil {
return woken, fmt.Errorf("wake expired defer %s rows affected: %w", id, err)
}
if n == 0 {
continue // rescued concurrently — leave it be
}
if err := RecordFullEventInTable(ctx, tx, eventsTable, id, types.EventStatusChanged,
DeferWakeActor, string(types.StatusDeferred), string(types.StatusOpen)); err != nil {
return woken, fmt.Errorf("record wake event for %s: %w", id, err)
}
// A wake is a status change, so it journals as an update. Emitted past
// the rows-affected re-check, so a concurrently-rescued bead records
// nothing.
if err := RecordEventInTx(ctx, tx, EventUpdate, id, DeferWakeActor); err != nil {
return woken, err
}
woken = append(woken, id)
}
return woken, nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause and verify the events table exists with the expected schema.
- Confirm the correct events table name is passed to WakeExpiredDefersInTx (not the issues table).
- Run storage migrations so the events table matches the current beads version.
- Retry after fixing — the transaction rolls back atomically so no partial state persists.
Example fix
// before: wrong table argument WakeExpiredDefersInTx(ctx, tx, "issues", "issues", now) // after WakeExpiredDefersInTx(ctx, tx, "issues", "issue_events", now)
Defensive patterns
Strategy: validation
Validate before calling
var exists string
err := db.QueryRow("SELECT TABLE_NAME FROM information_schema.TABLES WHERE TABLE_NAME='issue_events'").Scan(&exists)
if err != nil { return errors.New("issue_events table missing: run beads migration") } Try / catch
if err != nil {
return fmt.Errorf("wake transaction rolled back; issue %s remains deferred: %w", id, err)
// atomicity guarantees no half-woken state; fix events table and retry
} Prevention
- Run migrations so the events table always matches the code version.
- Pass the correct events table name (not the issues table) to wake APIs.
- Check disk space and constraint definitions on the events table.
- Trust transaction rollback: retry after fixing the cause leaves no partial state.
When it happens
Trigger: Calling WakeExpiredDefersInTx when inserting into the events table fails: missing/wrong events table name, schema mismatch in the events columns, connection failure, or constraint violation inside the transaction.
Common situations: Events table not created by migration; mismatched events-table parameter (issues table passed where events table expected); disk-full or duplicated-event constraint on the backend.
Related errors
- db: Claim %s: record event: %w
- inherit labels: insert %s on %s: %w
- failed to record claim event: %w
- ErrTransaction
- ErrQuery
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/670c4cffd57ab7fc.
Report an issue: GitHub.