Worktree checkout fails on Windows: checkout.workers=8 races and corrupts checkout (Background full checkout failed: other)
"Worktree" checkbox fails on Windows: parallel checkout.workers races and corrupts checkout
Summary
Starting a session with the Worktree option enabled fails every time on this machine with:
Couldn't switch branches Background full checkout failed: other
The underlying cause is that the desktop app runs the worktree's full checkout with a hardcoded-c checkout.workers=8. On this repo, on Windows, that parallel checkout reliably races while
creating a directory, aborts, and leaves the worktree half-populated. Serial checkout
(checkout.workers=1) succeeds every time with the identical command otherwise.
Environment
- OS: Windows Server 2025 Standard 10.0.26100
- git version 2.53.0.windows.2
- git-lfs 3.7.1 (installed, but not used by this repo — no paths tracked)
- Repo size: ~15 GB working tree (
Services/is one of ~35 top-level projects in a large multi-project .NET solution) - Windows Defender exclusion added for the repo path (
Add-MpPreference -ExclusionPath ...) — no effect, confirming this is not an antivirus/file-lock issue
Steps to reproduce
Reproducible with plain git, entirely outside the app:
cd <repo>
git worktree add --no-checkout ../wt-repro HEAD
cd ../wt-repro
git -c core.longpaths=true -c checkout.workers=8 checkout HEAD -- . ":(exclude).claude"
Result (every time):
warning: unable to unlink 'Services': Directory not empty
fatal: cannot create directory at 'Services': Directory not empty
Inspecting the half-written worktree afterward shows some top-level directories (e.g. .githooks,
part of Services/Tertios.MailProcessor/...) already materialized — i.e. several parallel checkout
workers had already written files before the worker handling Services hit the race and the whole
checkout aborted.
Control test — identical command, only checkout.workers changed:
git worktree remove --force ../wt-repro
git worktree add --no-checkout ../wt-repro2 HEAD
cd ../wt-repro2
git -c core.longpaths=true -c checkout.workers=1 checkout HEAD -- . ":(exclude).claude"
Exits 0, full checkout succeeds, every time.
Relevant app log (from %LOCALAPPDATA%/Claude/logs/main.log)
[info] Creating worktree for session local_... from <repo>
[info] [stageCheckout] Selective checkout done in 76ms (3 paths)
[info] Created worktree "..." at <repo>\.claude\worktrees\... (prep=111ms fetch=0ms/throttled add=64ms stage1=76ms git_spawns=11)
[info] Starting local session local_... in <repo>\.claude\worktrees\...
[info] Configured worktree hooks path to <repo>\.githooks (from base repo config)
[error] Git command failed: git -c core.longpaths=true -c checkout.workers=8 checkout HEAD -- . :(exclude).claude
{ code: 128, stderr: "warning: unable to unlink 'Services': Directory not empty\nfatal: cannot create directory at 'Services': Directory not empty\n" }
[warn] [CCD] first-turn init failed after worktree creation; removing orphaned worktree for local_...
[warn] Removing worktree "..." despite uncommitted changes at <repo>\.claude\worktrees\... (caller marked it never-used)
[error] Git command failed: git -c core.longpaths=true worktree remove --force <repo>\.claude\worktrees\...
{ code: 255, stderr: "error: failed to delete '...': Permission denied\n" }
[warn] Git worktree remove failed, will try manual cleanup: ...
[error] Failed to remove worktree directory EBUSY: resource busy or locked, rmdir '<repo>\.claude\worktrees\...'
[info] Removed worktree "..."
The follow-up worktree remove --force and directory rmdir also fail (Permission denied /EBUSY) on the same half-written directory, which is consistent with the aborted parallel checkout
leaving a file handle or partially-written entry behind under Services/ — not with an external
process (no AV, backup, or sync agent found to be involved; ruled out with a Defender exclusion and
process inspection).
This reproduced identically across 4 separate session attempts (different worktree names/dates),
always failing on the same top-level directory (Services) in this repo — i.e. it's a deterministic
repo-specific race, not a one-off fluke.
Impact
The Worktree option cannot be used at all on this repo/machine — every attempt fails and the
session never starts. Workaround is to not use the Worktree option.
Suggested fix
- Don't hardcode
checkout.workers=8for the worktree full-checkout step; either make it configurable,
fall back to serial (checkout.workers=1) on failure and retry, or drop the flag and let git's own
checkout.workers config/auto-detection decide.
- At minimum, retry the checkout once with
checkout.workers=1before giving up and surfacing
"Background full checkout failed: other" to the user — this alone would have avoided the failure
in all 4 observed attempts.
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗