Skip to content

fix: retry worktree removal on Windows when transient locks delay deletion#25

Open
jeremylasne92-hue wants to merge 2 commits into
craigsc:mainfrom
jeremylasne92-hue:fix-windows-rm-retry
Open

fix: retry worktree removal on Windows when transient locks delay deletion#25
jeremylasne92-hue wants to merge 2 commits into
craigsc:mainfrom
jeremylasne92-hue:fix-windows-rm-retry

Conversation

@jeremylasne92-hue
Copy link
Copy Markdown

Fixes #24

Problem

On Windows (Git Bash / MSYS), cmux rm fails with Directory not empty when the worktree contains a populated node_modules/. Background processes (npm watchers, esbuild, vitest) hold short-lived file handles inside node_modules after exit; git worktree remove runs its cleanup while a handle is still open → fails. The lock clears within ~1 second but cmux gives up immediately.

Fix

Retry git worktree remove up to 3 times with a 1-second backoff when running on MSYS/MinGW/Cygwin (uname -s matches MINGW*|MSYS*|CYGWIN*). Linux and macOS behavior is unchanged — they fall through to the original failure path with the existing error message.

Verification

On Windows Git Bash (MSYS2/MINGW64, bash 5.2.37, git 2.52.0.windows.1):

$ cd /c/path/to/node-repo
$ cmux new test-rm
# ...worktree created with node_modules/
$ cmux rm test-rm -f
# Before fix: error: failed to delete '...': Directory not empty
#             Failed to remove worktree: test-rm
# After fix:  Removed worktree and branch: test-rm   (succeeds on retry)

On Linux (no cygpath/MSYS detected): the case block is skipped entirely; the function behaves exactly as before. Existing error message and --force hint still trigger when the first attempt fails.

Scope

  • One function modified: _cmux_rm
  • 27 lines added, 1 removed
  • No new dependencies
  • No test additions (repo has no test suite per CLAUDE.md)

…etion

Sourced agents (npm, watchers) often hold short-lived locks on files inside node_modules right after exit; the first 'git worktree remove' then fails with 'Directory not empty' even though the lock clears in a second or two. Retry up to 3 times with a 1s backoff on MSYS/MinGW/Cygwin shells, leaving Linux/macOS behavior unchanged.
Field-tested 3x sleep 1 was insufficient for npm-loaded worktrees on Windows. Locks on node_modules native binaries (esbuild, vitest, .dll) can persist 5-8 seconds after process exit. Bump retry budget to 10s total, then fall back to rm -rf + git worktree prune if git still refuses to delete.
@jeremylasne92-hue
Copy link
Copy Markdown
Author

Field-tested on a real DANTE IA worktree (Node monorepo with vitest+esbuild). The initial 3x sleep 1 budget (3s total) was insufficient in practice — locks on node_modules native binaries persisted 5-8 seconds after the npm processes exited. Pushed an amendment (a48b817):

  • Retry budget bumped to 5x sleep 2 (10s total)
  • Last-resort fallback: rm -rf $worktree_dir && git worktree prune when git still refuses to delete a directory it cannot fully empty

This now succeeds reliably end-to-end on Windows for a 1.8 GB node_modules worktree. Linux/macOS branch is still skipped via the uname -s case.

@siennathesane
Copy link
Copy Markdown
Collaborator

I'm also onboard with this one, too!

I have an idea. If you can submit a new PR with a GitHub Actions runner for Windows that will at least bootstrap and run whatever tests are available, then I'm happy to merge #23 and #24 for you 🫶🏼 I just want to make sure things are properly supported.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] cmux rm fails on Windows when node_modules holds transient file locks

2 participants