macOS: intermittent 2-minute git hangs with core.fsmonitor enabled (multi-worktree/concurrent sessions); timeout SIGTERM orphans index.lock and wedges the session

Open 💬 0 comments Opened Jul 8, 2026 by nathanjohnpayne

Environment

  • Claude Code 2.1.204, macOS 26.5.2 (Darwin 25.5.0), Apple Silicon
  • git 2.50.1 (Apple Git-155)
  • Repos under ~/GitHub/<repo> with session worktrees under <repo>/.claude/worktrees/<slug>; typically several concurrent Claude Code sessions working the same repo through linked worktrees
  • Auto permission mode (sandboxed Bash)

Summary

With core.fsmonitor=true set, ordinary git commands inside Bash tool calls intermittently hang for the full 2-minute default timeout and die with exit 143 (SIGTERM). When the killed command was a git write, it leaves .git/worktrees/<slug>/index.lock behind, and every later git write in the session fails with fatal: Unable to create '...index.lock': File exists until the lock is manually removed — so one hung call wedges the rest of the session. Running git config core.fsmonitor false in the affected session immediately restored normal behavior, including a git fetch that had just timed out twice.

Incident timeline (2026-07-08, transcript timestamps UTC, one session)

  • 12:02:52 — git grep <term> on tracked files: Exit code 143 — Command timed out after 2m 0s
  • 12:11:36 — compound command containing git fetch: Exit code 143 — Command timed out after 2m 0s
  • 12:14:16 — next git write: Exit code 128 — fatal: Unable to create '.../.git/worktrees/<slug>/index.lock': File exists (no git process actually running; the lock was orphaned by the timed-out command)
  • 12:31–12:33 — compound containing git status --short: Exit code 143 — Command timed out after 2m 0s again; the model reports "my shell is unstable (SIGKILL/timeout on git)"
  • 12:44:36 — diagnosis in-session: "Fast git reads work; the 2-min hang was git status scanning the working tree (likely fsmonitor)"
  • 12:44:41 — remediation: git config core.fsmonitor false, git config core.untrackedcache true, export GIT_OPTIONAL_LOCKS=0, remove the orphaned lock
  • 12:44:46 — the previously-hanging git fetch origin main completes instantly (rc=0); git checkout -B <branch> succeeds; the session reports "everything ran clean after"

Prior independent incident (2026-06-02, different repo)

While diagnosing git index anomalies in a different repo on the same machine, a session found three stacked git fsmonitor--daemon run --detach --ipc-threads=8 processes for /Library/Developer/CommandLineTools/usr/libexec/git-core/git, which it attributed to "multiple worktrees/sessions".

Frequency

Scanning this machine's ~/.claude/projects transcripts: 30 sessions contain the Command timed out after marker, 8 sessions contain index.lock recovery work, and 2 sessions contain an explicit fsmonitor hang/diagnosis (2026-06-02 and 2026-07-08). The pattern spans at least five weeks and multiple repos.

What did and did not reproduce

A fresh repo under /private/tmp with core.fsmonitor=true, exercised inside a sandboxed Bash call, works fine: the daemon starts, git fsmonitor--daemon status reports watching, and git status returns in ~30ms. The hangs occurred on long-lived repos under ~/GitHub with a shared .git, multiple linked worktrees, and several concurrent Claude Code sessions. So the trigger looks like some combination of (a) multiple concurrent sessions racing to start/talk to the daemon across linked worktrees and (b) possibly sandbox restrictions on the daemon IPC socket (.git/fsmonitor--daemon.ipc) under $HOME when the daemon was started by a different process — rather than fsmonitor per se.

Impact and workaround

One hung git call wedges the session (timeout → orphaned index.lock → every write fails), and recovery burns many turns. Workaround that has held: git config --global core.fsmonitor false plus removing the orphaned lock.

Suggestions

  • When the Bash tool times out and kills a git process, consider detecting/surfacing an orphaned index.lock (or hinting at it in the timeout error). The current downstream failure mode — File exists on every later write — is a confusing cascade.
  • Investigate whether the sandbox profile permits connecting to an existing fsmonitor--daemon IPC socket under $HOME when the daemon was spawned by another (unsandboxed or other-session) process, and whether git then blocks instead of failing fast.
  • Consider documenting core.fsmonitor false as the known-good configuration for multi-session / multi-worktree use on macOS.

Full sanitized transcript excerpts available on request.

View original on GitHub ↗