gastownhall/beads · error

dolt clone failed: %w Output: %s

Error message

dolt clone failed: %w
Output: %s

What it means

This branch of formatFailedCloneTargetError fires when `dolt clone` failed and cleanup of the partial clone target could not even be attempted: os.Lstat of the target's .dolt directory failed with an error other than NotExist (cleaned=false is not reachable here; this is the cleanupErr==nil, cleaned==false path where Lstat reported the .dolt dir absent/non-dir). No cleanup was performed, so the leftover directory may still be on disk.

Source

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

	for attempt := 0; ; attempt++ {
		err := os.RemoveAll(path)
		if err == nil || os.IsNotExist(err) {
			return true, nil
		}
		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)

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the Output section to identify and fix the underlying dolt clone failure first.
  2. Inspect the leftover target directory (`ls -la <doltDir>/<db>`); if it is debris, remove it manually with `rm -rf` after verifying it is not a repo you need.
  3. If target/.dolt is a symlink or non-directory, remove that entry specifically and retry.
  4. Retry `bd bootstrap` once the target is clean and the clone root cause is fixed.

Example fix

# before
$ ls -la .beads/dolt/beads/.dolt   # symlink left by an earlier tool
$ bd bootstrap                     # clone failed; no cleanup done
# after
$ rm -f .beads/dolt/beads/.dolt && rm -rf .beads/dolt/beads
$ bd bootstrap
Defensive patterns

Strategy: try-catch

Validate before calling

if fi, err := os.Lstat(filepath.Join(doltDir, db, ".dolt")); err == nil && !fi.IsDir() {
    // .dolt is a file/symlink: clean it up before bootstrapping
}

Try / catch

if err != nil && strings.Contains(err.Error(), "dolt clone failed") {
    // manually inspect/remove the leftover target, then retry bootstrap
    _ = os.RemoveAll(filepath.Join(doltDir, db))
}

Prevention

When it happens

Trigger: `dolt clone` fails on a non-pre-existing target, removeFailedCloneTargetWithRetry returns cleaned=false with cleanupErr=nil — i.e. the target has no .dolt subdirectory (or it is not a plain directory), so the function declines to delete it.

Common situations: dolt failed so early that it created only an empty or partial target with no .dolt; a symlink or file sits at target/.dolt so cleanup refuses to touch it; unusual filesystem where Lstat metadata is unreliable.

Related errors


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