gastownhall/beads · error

failed to commit orphaned dependency removals: %w

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.

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)

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.