gastownhall/beads · error
delete: drop events: %w
Error message
delete: drop events: %w
What it means
This error means deleting event rows for the regular issues being deleted failed. During deleteMany, eventsRepo.DeleteAllForIDs removes the issue history after labels; failure aborts the delete so events are never left for removed issues.
Source
Thrown at internal/storage/domain/issue_delete.go:190
// The SYNC-PLANE edges pointing at a deleted wisp, which are not the same
// rows as the line above and are not reached by a foreign key: there is no
// FK from dependencies to wisps, so `dependencies.depends_on_wisp_id` rows
// survive their target unless they are deleted explicitly. Without this a
// forced delete of a wisp left its durable dependent holding an edge into
// a row that no longer exists — dangling, not orphaned, which is not what
// issueops.DeleteRequest.Force promises. The store body has always done
// this (issueops.deleteIssueRowInTx -> DeleteWispFromDependenciesInTx).
if _, err := u.depRepo.DeleteAllForIDs(ctx, wispIDs, DepInsertOpts{}); err != nil {
return result, fmt.Errorf("delete: drop sync-plane edges into deleted wisps: %w", err)
}
if _, err := u.labelRepo.DeleteAllForIDs(ctx, regularIDs, LabelOpts{}); err != nil {
return result, fmt.Errorf("delete: drop labels: %w", err)
}
if _, err := u.labelRepo.DeleteAllForIDs(ctx, wispIDs, LabelOpts{UseWispsTable: true}); err != nil {
return result, fmt.Errorf("delete: drop wisp labels: %w", err)
}
if _, err := u.eventsRepo.DeleteAllForIDs(ctx, regularIDs, RecordEventOpts{}); err != nil {
return result, fmt.Errorf("delete: drop events: %w", err)
}
if _, err := u.eventsRepo.DeleteAllForIDs(ctx, wispIDs, RecordEventOpts{UseWispsTable: true}); err != nil {
return result, fmt.Errorf("delete: drop wisp events: %w", err)
}
issuesDeleted, err := u.issueRepo.DeleteByIDs(ctx, regularIDs, IssueTableOpts{})
if err != nil {
return result, fmt.Errorf("delete: drop issue rows: %w", err)
}
wispsDeleted, err := u.issueRepo.DeleteByIDs(ctx, wispIDs, IssueTableOpts{UseWispsTable: true})
if err != nil {
return result, fmt.Errorf("delete: drop wisp rows: %w", err)
}
result.DeletedCount = issuesDeleted + wispsDeleted
if params.UpdateTextReferences && len(connected) > 0 {
refs, err := u.rewriteTextReferences(ctx, allIDs, connected, connectedIsWisp, actor)
if err != nil {View on GitHub (pinned to 71377f2769)
Solutions
- Confirm the events table exists and is writable; run migrations if stale.
- Retry the delete; transactional scope prevents partial event removal.
- Inspect the wrapped cause (lock timeout, disk full, permissions) and fix.
- Archive/prune the events table if its size is causing timeouts.
Defensive patterns
Strategy: validation
Validate before calling
if err := ctx.Err(); err != nil { return err }
exists, err := tableExists(ctx, "events"); if err != nil || !exists { return fmt.Errorf("events table missing") }
// optionally prune: rows, _ := countRows(ctx, "events") Type guard
var dbe *storage.DBError
if errors.As(err, &dbe) { /* inspect driver cause */ } Try / catch
if err := store.DeleteIssues(ctx, ids, opts); err != nil {
if strings.Contains(err.Error(), "delete: drop events:") { /* check lock timeouts / retry */ }
} Prevention
- Prune/archive large events tables to keep deletes fast.
- Keep adequate lock_wait_timeout for the driver.
- Migrate stale schemas.
- Set generous context deadlines for deletes.
When it happens
Trigger: DeleteIssue/DeleteIssues calls where the events table is unwritable (missing table, insufficient privileges, lock contention) or the connection/context fails during the cascade.
Common situations: Events table very large causing long DELETE times and lock wait timeouts; schema drift in embedded Dolt; DB restarted mid-operation.
Related errors
- db: EventsSQLRepository.DeleteAllForIDs from %s: %w
- delete: drop deps: %w
- delete: drop wisp deps: %w
- delete: drop labels: %w
- delete: drop wisp events: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/b2c3517ab5f892db.
Report an issue: GitHub.