gastownhall/beads · error

dolt clone failed: %w Output: %s Could not inspect failed cl

Error message

dolt clone failed: %w
Output: %s
Could not inspect failed clone target %q before cleanup: %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 branch of formatFailedCloneTargetError fires when `dolt clone` failed AND cleanup of the partial clone target could not even be inspected: os.Lstat of the target's .dolt returned a non-NotExist error. The message is Windows-centric — it almost always means another process (dolt, bd, or an antivirus scanner) still holds a handle under .dolt/noms/LOCK, so the partial clone is left in place with remediation instructions.

Source

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

		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)
}

// pathExists reports whether path exists (of any type), without following

View on GitHub (pinned to 71377f2769)

Solutions

  1. Wait a few seconds and retry `bd bootstrap` — the error text's cleanup retry loop (50ms–500ms) may simply need longer for the lock to release.
  2. Kill any stuck dolt/bd processes (Task Manager or `taskkill /F /IM dolt.exe`) that still hold handles under the target directory.
  3. Add an antivirus/Defender exclusion for the workspace's .beads directory so the scanner stops locking .dolt/noms/LOCK.
  4. If the partial directory remains, delete it manually (`rm -rf .beads/dolt/<db>` or Explorer) once handles are released, then retry.
  5. Move the workspace off network-synced storage (OneDrive/Dropbox/SMB share) to a local disk if locking recurs.

Example fix

# before (Windows): clone failed, LOCK held
$ bd bootstrap
#   Could not inspect failed clone target ... .dolt/noms/LOCK
# after: release the handle, clean up, retry
$ taskkill /F /IM dolt.exe
$ rmdir /s /q .beads\dolt\beads
$ bd bootstrap
Defensive patterns

Strategy: retry

Try / catch

if err != nil && strings.Contains(err.Error(), "Could not inspect failed clone target") {
    time.Sleep(2 * time.Second) // let AV/scanner release .dolt/noms/LOCK
    // retry bootstrap or clean up manually
}

Prevention

When it happens

Trigger: `dolt clone` fails, then removeFailedCloneTargetWithRetry's os.Lstat(<target>/.dolt) errors with something other than NotExist (permission denied, sharing violation, I/O error) — classic Windows file-locking on .dolt/noms/LOCK right after a failed dolt process exits.

Common situations: Windows machines where Defender or another AV scans the freshly written .dolt files immediately after a failed clone; a lingering dolsql/dolt process holding the noms LOCK; OneDrive/Dropbox sync locking .beads paths; the repo living on a network share with handle delays.

Related errors


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