gastownhall/beads · error
affected by delete for %s: %w
Error message
affected by delete for %s: %w
What it means
DeleteIssueInTx wraps a failure from AffectedByDeletionInTx — the query that computes which issues/wisps depend on the issue being deleted so their is_blocked flags can be recomputed. The wrapped error (%w) is the underlying SQL/query failure, not a 'not found' condition. The %s is the id of the issue whose deletion triggered the dependency scan.
Source
Thrown at internal/storage/issueops/delete.go:34
const deleteBatchSize = 50
// maxRecursiveResults is the safety limit for the total number of issues
// discovered during recursive dependent traversal.
const maxRecursiveResults = 10000
//nolint:gosec // G201: table names come from WispTableRouting (hardcoded constants)
func DeleteIssueInTx(ctx context.Context, tx *sql.Tx, id string) error {
isWisp := IsActiveWispInTx(ctx, tx, id)
var deletedIssues, deletedWisps []string
if isWisp {
deletedWisps = []string{id}
} else {
deletedIssues = []string{id}
}
affectedIssues, affectedWisps, aerr := AffectedByDeletionInTx(ctx, tx, deletedIssues, deletedWisps)
if aerr != nil {
return fmt.Errorf("affected by delete for %s: %w", id, aerr)
}
// Edges are journaled before the rows go, while their source snapshots can
// still be read.
if err := RecordDependencyRemovalsForIssuesInTx(ctx, tx, []string{id}); err != nil {
return fmt.Errorf("journal dependency removals for %s: %w", id, err)
}
if err := deleteIssueRowInTx(ctx, tx, id, isWisp); err != nil {
return err
}
if err := RecomputeIsBlockedInTx(ctx, tx, affectedIssues, affectedWisps); err != nil {
return fmt.Errorf("recompute is_blocked after delete for %s: %w", id, err)
}
return nil
}
View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause (%w) — the error is only a wrapper; the root cause is in err.Unwrap()/the chain.
- Check that the caller's context was not canceled/expired before the delete; raise the timeout for large dependency graphs.
- Verify DB connectivity and transaction health (no prior error on the same tx — a failed statement can poison the tx).
- Retry the whole delete operation on a fresh transaction if the failure was transient (connection reset, deadlock).
Example fix
// before: reusing a long-lived context that expired mid-delete err := storage.DeleteIssue(ctxWith5sTimeout, db, id) // after: use a fresh, adequately-long context per delete delCtx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() err := storage.DeleteIssue(delCtx, db, id)
Defensive patterns
Strategy: retry
Validate before calling
if err := ctx.Err(); err != nil { return fmt.Errorf("context already expired before delete: %w", err) }
if err := db.PingContext(ctx); err != nil { return fmt.Errorf("db unreachable before delete: %w", err) } Try / catch
if err := storage.DeleteIssue(ctx, db, id); err != nil {
if isTransient(err) { // net.Error, driver.ErrBadConn, lock timeout
// retry once on a fresh tx + fresh context
}
return fmt.Errorf("delete %s: %w", id, err)
} Prevention
- Give delete operations a dedicated, generously-sized context instead of reusing request-scoped short deadlines.
- Never reuse a transaction handle after any prior error on it.
- Watch dependency-graph size before deleting hub issues.
When it happens
Trigger: Calling storage.DeleteIssue / DeleteIssueInTx when AffectedByDeletionInTx fails: the underlying tx is broken (rolled back, timeout, context canceled) or the dependency-plane query fails (connection dropped, lock timeout, driver error).
Common situations: Deleting an issue while the DB connection was interrupted mid-transaction; context deadline exceeded because the dependency scan hit a large dependency graph on a slow Dolt server; lock contention with a concurrent writer on dependencies tables.
Related errors
- failed to close issue: %w
- recompute is_blocked after close for %s: %w
- journal dependency removals for %s: %w
- recompute is_blocked after delete for %s: %w
- expand cascade: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/ec16f0e7ce029ad3.
Report an issue: GitHub.