gastownhall/beads · error
affected by source-repo delete: %w
Error message
affected by source-repo delete: %w
What it means
Before deleting, the function computes which remaining issues/wisps are affected via AffectedByDeletionInTx; failure is wrapped as "affected by source-repo delete: %w". This is an internal dependency-graph query inside the same transaction.
Source
Thrown at internal/storage/issueops/bulk_ops.go:197
}
var issueIDs []string
for rows.Next() {
var id string
if err := rows.Scan(&id); err != nil {
_ = rows.Close()
return 0, fmt.Errorf("scan issue ID: %w", err)
}
issueIDs = append(issueIDs, id)
}
_ = rows.Close()
if len(issueIDs) == 0 {
return 0, nil
}
affectedIssues, affectedWisps, aerr := AffectedByDeletionInTx(ctx, tx, issueIDs, nil)
if aerr != nil {
return 0, fmt.Errorf("affected by source-repo delete: %w", aerr)
}
// Deleted issues hold no leases: clear them while the id set is still
// joinable (before the issues rows go away).
if _, err := tx.ExecContext(ctx,
`DELETE FROM leases WHERE issue_id IN (SELECT id FROM issues WHERE source_repo = ?)`, sourceRepo); err != nil {
return 0, fmt.Errorf("delete leases: %w", err)
}
// Edges are journaled before the rows go, while their source snapshots can
// still be read.
if err := RecordDependencyRemovalsForIssuesInTx(ctx, tx, issueIDs); err != nil {
return 0, fmt.Errorf("journal dependency removals for source-repo delete: %w", err)
}
result, err := tx.ExecContext(ctx, `DELETE FROM issues WHERE source_repo = ?`, sourceRepo)
if err != nil {
return 0, fmt.Errorf("delete issues: %w", err)View on GitHub (pinned to 71377f2769)
Solutions
- Check the inner error from AffectedByDeletionInTx for the failing statement
- Verify dependencies-related tables exist (schema up to date)
- Retry the transaction with a longer context deadline for large graphs
- Confirm the tx is healthy; begin a fresh transaction if a prior statement rolled it back
Defensive patterns
Strategy: retry
Validate before calling
// pre-check dependency tables exist
_, err := db.Query("SELECT 1 FROM dependencies LIMIT 1") Type guard
if errors.Is(err, context.Canceled) { /* abort, do not retry */ } Try / catch
err := DeleteIssuesBySourceRepoInTx(ctx, tx, repo)
if isTransientDBErr(err) { // busy/locked
time.Sleep(backoff)
err = retryWholeTransaction(ctx, repo)
} Prevention
- Schedule bulk deletes during low write contention
- Retry the full transaction atomically rather than individual steps
- Use exponential backoff for busy/locked driver errors
When it happens
Trigger: AffectedByDeletionInTx returns an error: its internal queries fail (missing dependency/blocking tables), the transaction is aborted, or the context is canceled while computing the affected set.
Common situations: Schema drift (dependencies table missing or renamed); timeout on repos with very large dependency graphs; tx invalidated by an earlier failed statement in the caller's transaction.
Understand the failure class
Background: "query failed", "%w: SQL error" — wrapped database query errors in Go libraries explained — this error's family across 3 libraries.
Related errors
- applyGraph: read existing deps for %s: %w
- applyGraph: read existing wisp deps for %s: %w
- query issues: %w
- delete issues: %w
- recompute is_blocked after close for %s: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/4a2e8df5c129420d.
Report an issue: GitHub.