gastownhall/beads · error
db: record event in %s: %w
Error message
db: record event in %s: %w
What it means
Wraps failures recording an event row into either the events or wisp_events table via issueops.RecordFullEventInTable. The %s names which table was targeted. Unlike some wisp paths, this does not tolerate missing tables, so any insert failure surfaces here.
Source
Thrown at internal/storage/domain/db/events.go:29
)
func NewEventsSQLRepository(runner Runner) domain.EventsSQLRepository {
return &eventsSQLRepositoryImpl{runner: runner}
}
type eventsSQLRepositoryImpl struct {
runner Runner
}
var _ domain.EventsSQLRepository = (*eventsSQLRepositoryImpl)(nil)
func (r *eventsSQLRepositoryImpl) Record(ctx context.Context, evt domain.Event, opts domain.RecordEventOpts) error {
table := "events"
if opts.UseWispsTable {
table = "wisp_events"
}
if err := issueops.RecordFullEventInTable(ctx, r.runner, table, evt.IssueID, evt.Type, evt.Actor, evt.OldValue, evt.NewValue); err != nil {
return fmt.Errorf("db: record event in %s: %w", table, err)
}
return nil
}
func (r *eventsSQLRepositoryImpl) DeleteAllForIDs(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"
}
total := 0
for start := 0; start < len(ids); start += deleteBatchSize {
end := start + deleteBatchSize
if end > len(ids) {
end = len(ids)
}View on GitHub (pinned to 71377f2769)
Solutions
- Check the wrapped driver error for FK violations or missing-table errors
- Run schema migrations so the events table exists (bd migrate / dolt schema ensure)
- Verify the target issue exists before recording the event
- Check disk/replication state if the DB is read-only
Example fix
// before
err := eventsRepo.Record(ctx, evt, domain.RecordEventOpts{})
// after
if _, err := issueRepo.Get(ctx, evt.IssueID, opts); err == nil {
err = eventsRepo.Record(ctx, evt, domain.RecordEventOpts{})
} Defensive patterns
Strategy: try-catch
Validate before calling
if evt.IssueID == "" { return fmt.Errorf("event requires IssueID") }
if _, err := issueRepo.Get(ctx, evt.IssueID, tableOpts); err != nil {
return fmt.Errorf("target issue %s missing, skipping event", evt.IssueID)
} Type guard
func isFKViolation(err error) bool {
var mysqlErr *go_mysql.MySQLError
return errors.As(err, &mysqlErr) && mysqlErr.Number == 1452
} Try / catch
if err := eventsRepo.Record(ctx, evt, opts); err != nil {
if isFKViolation(err) { log.Warnf("event for deleted issue %s dropped", evt.IssueID); return nil }
return fmt.Errorf("record event: %w", err)
} Prevention
- Verify the target issue exists before recording
- Keep old/new values within column size limits
- Run migrations so events/wisp_events exist
- Avoid recording events on read-only replicas
When it happens
Trigger: Calling Record with opts.UseWispsTable=false and a missing/nonexistent events table, an invalid evt.IssueID violating a foreign key, oversized old/new values, connection failure, or a read-only replica.
Common situations: Recording an event for an issue that was deleted mid-transaction (FK violation); database in read-only mode; schema not yet migrated so the events table is absent.
Related errors
- failed to seed issue_counter for prefix %q at %d: %w
- failed to insert initial issue counter for prefix %q: %w
- db: CommentSQLRepository.Insert: %w
- db: DependencySQLRepository.Insert: record dependency_added
- db: DependencySQLRepository.Delete: record dependency_remove
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/155a08cf9c679b41.
Report an issue: GitHub.