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

  1. Check the inner error from AffectedByDeletionInTx for the failing statement
  2. Verify dependencies-related tables exist (schema up to date)
  3. Retry the transaction with a longer context deadline for large graphs
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/4a2e8df5c129420d. Report an issue: GitHub.