gastownhall/beads · error
delete: resolve ids: %w
Error message
delete: resolve ids: %w
What it means
This error wraps a failure from GetIssuesByIDsInTx while DeleteInTx (the store-backed body of `bd delete`) resolves the requested ids to rows inside the delete transaction. It runs after the wisp-plane classification, so any SQL-level or driver-level failure during the batched id lookup surfaces here with the 'delete: resolve ids' prefix. It is an infrastructure wrapper, not a domain refusal — absent ids surface separately as a NotFoundError.
Source
Thrown at internal/storage/issueops/delete_role.go:42
// BEFORE opening a transaction, so a malformed request costs no database work.
//
// THE REWRITE IS INSIDE THE TRANSACTION. A route that deleted the rows in one
// transaction and rewrote the neighbors' text afterwards left, on a failure
// between the two, a workspace whose rows were gone and whose descriptions
// still cited them.
func DeleteInTx(ctx context.Context, tx *sql.Tx, req publicops.DeleteRequest) (publicops.DeleteResult, error) {
ids := req.IDs
result := publicops.DeleteResult{DryRun: req.DryRun}
// The existence probe comes FIRST, so `bd delete typo real` reports the
// typo rather than whatever the graph says about the id that resolved.
wispSet, err := WispIDSetInTx(ctx, tx, ids)
if err != nil {
return publicops.DeleteResult{}, fmt.Errorf("delete: classify planes: %w", err)
}
found, err := GetIssuesByIDsInTx(ctx, tx, ids, wispSet)
if err != nil {
return publicops.DeleteResult{}, fmt.Errorf("delete: resolve ids: %w", err)
}
present := make(map[string]bool, len(found))
for _, issue := range found {
if issue != nil {
present[issue.ID] = true
}
}
var missing []string
for _, id := range ids {
if !present[id] {
missing = append(missing, id)
}
}
if len(missing) > 0 {
return publicops.DeleteResult{}, &publicops.NotFoundError{IDs: missing}
}
// The version precondition sits between the existence probe and theView on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped error (%w / errors.Unwrap) for the real driver message
- Check database connectivity and that the transaction is still alive (no prior error/rollback)
- Verify the storage schema is current (run migrations / `bd doctor`)
- Retry the delete with a fresh transaction if the context was cancelled or the connection dropped
- Reduce batch size or split large id lists if timeouts are the cause
Example fix
// before: unbounded ctx
res, err := store.Delete(ctx, req)
// after: bound the operation and handle context expiry
ctx, cancel := context.WithTimeout(ctx, 30*time.Second)
defer cancel()
res, err := store.Delete(ctx, req)
if err != nil && strings.Contains(err.Error(), "delete: resolve ids") { /* check DB health, retry */ } Defensive patterns
Strategy: try-catch
Validate before calling
ids := normalizeDeleteIDs(req.IDs)
if len(ids) == 0 { return errors.New("no ids to delete") }
if err := ctx.Err(); err != nil { return err } // ctx must be live before opening the tx Type guard
var serr *publicops.NotFoundError
if errors.As(err, &serr) { /* domain refusal, not an infra failure */ }
// otherwise the 'delete: resolve ids' wrapper indicates a storage failure Try / catch
res, err := store.Delete(ctx, req)
if err != nil {
if strings.Contains(err.Error(), "delete: resolve ids") {
// storage-layer failure; check DB health, retry with fresh tx
}
return err
} Prevention
- Always pass a live, adequately-budgeted context to Delete
- Keep schema migrations current before running deletes
- Monitor DB connectivity before batch deletes
- Use DryRun first to exercise the read path before the real delete
When it happens
Trigger: DeleteInTx (or DeleteIssuesInTx via issueops.Deleter) calls GetIssuesByIDsInTx over the requested ids and the underlying query/scan/rows iteration fails — driver error, context cancellation mid-query, or a broken connection inside the open transaction.
Common situations: Database connection dropped or transaction invalidated before the probe; context deadline exceeded during a large --from-file batch; backend schema drift breaking the issues lookup; partially migrated database.
Related errors
- delete: drop deps: %w
- delete: drop wisp deps: %w
- delete: drop labels: %w
- delete: drop events: %w
- delete: drop issue rows: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/5c12c38c5e466a94.
Report an issue: GitHub.