gastownhall/beads · error

dolt clone failed: %w Output: %s Could not clean up failed c

Error message

dolt clone failed: %w
Output: %s
Could not clean up failed clone target %q after retrying: %v
On Windows this usually means a dolt or bd process, or antivirus scanner, still has a file handle open under `.dolt/noms/LOCK`. Stop stuck dolt/bd processes, wait a moment, delete the directory manually if it remains, then retry `bd bootstrap`

What it means

This error wraps a failure of the underlying `dolt clone` command during `bd bootstrap` (cloning a remote Dolt database), and additionally reports that the partially-created clone target directory could not be deleted during cleanup. It appears only when both the clone failed AND a post-failure cleanup retry of os.RemoveAll failed. On Windows this is almost always a file-handle/locking issue on files under the clone directory (e.g. `.dolt/noms/LOCK`).

Source

Thrown at internal/storage/dolt/bootstrap.go:144

		}
		if attempt >= len(failedCloneCleanupRetryDelays) {
			return true, err
		}
		time.Sleep(failedCloneCleanupRetryDelays[attempt])
	}
}

func formatFailedCloneTargetError(cloneErr error, output []byte, cloneTarget string, cleaned bool, cleanupErr error) error {
	if cleanupErr == nil && cleaned {
		return fmt.Errorf("dolt clone failed: %w\nOutput: %s\nCleaned up failed clone target %q; fix the clone error above and retry `bd bootstrap`", cloneErr, output, cloneTarget)
	}
	if cleanupErr == nil {
		return fmt.Errorf("dolt clone failed: %w\nOutput: %s", cloneErr, output)
	}
	if !cleaned {
		return fmt.Errorf("dolt clone failed: %w\nOutput: %s\nCould not inspect failed clone target %q before cleanup: %v\nOn Windows this usually means a dolt or bd process, or antivirus scanner, still has a file handle open under `.dolt/noms/LOCK`. Stop stuck dolt/bd processes, wait a moment, delete the directory manually if it remains, then retry `bd bootstrap`", cloneErr, output, cloneTarget, cleanupErr)
	}
	return fmt.Errorf("dolt clone failed: %w\nOutput: %s\nCould not clean up failed clone target %q after retrying: %v\nOn Windows this usually means a dolt or bd process, or antivirus scanner, still has a file handle open under `.dolt/noms/LOCK`. Stop stuck dolt/bd processes, wait a moment, delete the directory manually if it remains, then retry `bd bootstrap`", cloneErr, output, cloneTarget, cleanupErr)
}

func doltCloneArgs(remoteURL, target string) []string {
	args := []string{"clone"}
	if user := os.Getenv("DOLT_REMOTE_USER"); user != "" {
		args = append(args, "--user", user)
	}
	return append(args, remoteURL, target)
}

// BootstrapFromGitRemoteWithDB is deprecated. Use BootstrapFromRemoteWithDB instead.
func BootstrapFromGitRemoteWithDB(ctx context.Context, doltDir, gitRemoteURL, database string) (bool, error) {
	return BootstrapFromRemoteWithDB(ctx, doltDir, gitRemoteURL, database)
}

// pathExists reports whether path exists (of any type), without following
// symlinks. Used to detect whether a clone target pre-existed before a
// clone attempt, so failed-clone cleanup never deletes something it didn't

View on GitHub (pinned to 71377f2769)

Solutions

  1. Stop any running dolt/bd processes (task manager / `taskkill` or `pkill dolt`), then retry `bd bootstrap`
  2. On Windows, wait a few seconds for the AV scanner to release handles, then delete the target directory manually and retry `bd bootstrap`
  3. Inspect the wrapped clone error and `Output:` section for the root cause of the clone itself (auth, URL, network) and fix that before retrying
  4. Reboot or close any programs (Explorer, editors) holding the directory open, then retry

Example fix

// before (manual recovery)
rm -rf ./path/to/failed-clone-target
bd bootstrap
// after (ensure no lingering processes first)
pkill dolt; pkill bd
rm -rf ./path/to/failed-clone-target
bd bootstrap
Defensive patterns

Strategy: try-catch

Validate before calling

// before bootstrap: ensure no clone target exists and no stale handles
if _, err := os.Stat(target); err == nil {
    if err := os.RemoveAll(target); err != nil {
        // another process/AV holds handles; stop dolt/bd processes first
    }
}

Try / catch

var bootErr *os.PathError
if err := bd.BootstrapFromRemoteWithDB(ctx, url, target); err != nil {
    if strings.Contains(err.Error(), "Could not clean up failed clone target") {
        // stop dolt/bd processes, wait, manually os.RemoveAll(target), retry once
    } else if errors.As(err, &bootErr) {
        // fix path-level clone problem reported in Output:
    }
}

Prevention

When it happens

Trigger: BootstrapFromRemoteWithDB calls dolt clone; the clone itself errors (bad remote URL, auth failure, network down, corrupt remote), then the code tries to remove the leftover target directory and that removal fails, typically because a dolt/bd process or antivirus scanner holds an open handle to a file under the directory.

Common situations: Stale dolt server processes from a previous crashed bootstrap; Windows Defender or another AV scanner scanning freshly written `.dolt/noms` files during cleanup; the target directory being open in Explorer, a shell, or an editor; insufficient permissions on the target path.

Related errors


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