gastownhall/beads · error

failed to commit orphaned dependency removals

Error message

failed to commit orphaned dependency removals: %w

What it means

After deleting orphaned dependency rows inside an explicit transaction, OrphanedDependencies calls tx.Commit(). Because Dolt may run with autocommit disabled, this commit is what makes the deletions durable — if it fails, the wrapped error is returned and none of the removals are persisted (the transaction rolls back). This error appears only after individual DELETEs succeeded on the connection.

Solutions

  1. Re-run `bd doctor --fix` after confirming the Dolt server is healthy — the transaction rolled back, so the fix is safely repeatable.
  2. Check server logs and disk space; resolve storage errors (disk full, corrupted sstables) before retrying.
  3. Ensure no other session holds locks on dependencies/wisp_dependencies (lock wait timeout); close competing bd processes.
  4. If the server runs with --no-auto-commit, verify it accepts explicit commits and isn't in a read-only or shutting-down state.

Example fix

// before: server dropped connection during DELETE loop
if err := tx.Commit(); err != nil {
	return fmt.Errorf("failed to commit orphaned dependency removals: %w", err)
}
// after: restart dolt server, ensure free disk, then re-run the fix
// dolt server &  # healthy restart; orphan removals are re-applied from scratch
if err := tx.Commit(); err != nil {
	return fmt.Errorf("failed to commit orphaned dependency removals: %w", err) // succeeds
}
Defensive patterns

Strategy: retry

Validate before calling

// check free disk and server health before running deletions
if err := db.PingContext(ctx); err != nil {
	return fmt.Errorf("server unhealthy before fix: %w", err)
}
// and on the host: df -h <dolt_data_dir>

Type guard

var lockErr *driver.Error
if errors.As(err, &lockErr) && (lockErr.Number == 1205 || lockErr.Number == 1213) {
	// lock wait timeout / deadlock — wait and retry the fix
}

Try / catch

if err := fix.OrphanedDependencies(path, verbose); err != nil {
	if strings.Contains(err.Error(), "failed to commit") {
		// transaction rolled back; nothing persisted — safe to re-run
		time.Sleep(2 * time.Second)
		err = fix.OrphanedDependencies(path, verbose)
	}
	if err != nil {
		log.Fatalf("orphan removals not committed: %v", err)
	}
}

Prevention

When it happens

Trigger: tx.Commit() fails at validation.go:108 — the connection to the Dolt server dropped during the DELETE loop, the server rejected the commit (e.g. storage error, deadlock/lock wait timeout, server shutting down with --no-auto-commit), or the transaction was already invalidated by an earlier session-level error.

Common situations: Dolt server killed mid-fix so buffered writes can't be committed; disk-full or storage backend failure on the server; lock conflicts with another session holding row/table locks on `dependencies`/`wisp_dependencies`; long DELETE loop exceeding a lock-wait timeout before Commit.

Related errors


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

Appendix: source

Thrown at cmd/bd/doctor/fix/validation.go:109

		case "dependencies":
			_, err = tx.Exec("DELETE FROM dependencies WHERE issue_id = ? AND "+fixDependencyTargetExpr+" = ?", o.issueID, o.dependsOnID)
		case "wisp_dependencies":
			_, err = tx.Exec("DELETE FROM wisp_dependencies WHERE issue_id = ? AND "+fixDependencyTargetExpr+" = ?", o.issueID, o.dependsOnID)
		default:
			fmt.Printf("  Warning: skipped orphaned dependency from unexpected table %s\n", o.depTable)
			continue
		}
		if err != nil {
			fmt.Printf("  Warning: failed to remove %s→%s: %v\n", o.issueID, o.dependsOnID, err)
		} else {
			removed++
			if showIndividual {
				fmt.Printf("  Removed orphaned dependency: %s→%s\n", o.issueID, o.dependsOnID)
			}
		}
	}
	if err := tx.Commit(); err != nil {
		return fmt.Errorf("failed to commit orphaned dependency removals: %w", err)
	}

	// Commit changes in Dolt
	_, _ = db.Exec("CALL DOLT_COMMIT('-Am', 'doctor: remove orphaned dependencies')") // Best effort: commit advisory; schema fix already applied in-memory

	fmt.Printf("  Fixed %d orphaned dependency reference(s)\n", removed)
	return nil
}

// ChildParentDependencies removes child→parent blocking dependencies.
// These often indicate a modeling mistake (deadlock: child waits for parent, parent waits for children).
// Requires explicit opt-in via --fix-child-parent flag since some workflows may use these intentionally.
// If verbose is true, prints each removed dependency; otherwise shows only summary.
func ChildParentDependencies(path string, verbose bool) error {
	beadsDir, err := resolvedWorkspaceBeadsDir(path)
	if err != nil {
		return err
	}

View on GitHub (pinned to 71377f2769)