claude-code - 💡(How to fix) Fix Cowork sandbox (virtiofs bind-mount) silently drops git unlink() with EPERM, leaving stale tmp_obj_* files and .lock files on host

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

Root Cause

Root cause (diagnosed)

Fix Action

Fix / Workaround

Workaround deployed (user-side)

Host-side launchd agent running every 300 s removes tmp_obj_* files older than 300 s with nlink ≥ 2, and .lock files older than 300 s. This is a host-side patch for a sandbox-side bug.

Code Example

fatal: Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes are
terminated then try again.

---

# Sample: named object and stranded tmp name are the same inode
.git/objects/3b/
  -r--r--r--  2  tonypurkins  7fb24114514b5d7c324bc88eca2f0f79694f26   ← named object
  -r--r--r--  2  tonypurkins  tmp_obj_IRVfqf                            ← stranded tmp, same inode
RAW_BUFFERClick to expand / collapse

Environment

  • macOS host (Darwin 25.5.0), repos bind-mounted into Linux sandbox via com.apple.Virtualization.VirtualMachine.xpc
  • Sandbox uid (wonderful-magical-hawking) differs from host owner uid
  • Affects all repos Cowork touches — reproduced across 5 separate repos in one studio

Symptom

After a Cowork session, .git/objects/*/tmp_obj_* files accumulate on the host filesystem. Stale .git/index.lock and .git/HEAD.lock files also persist after session-kill, blocking host-side git operations with:

fatal: Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes are
terminated then try again.

Inside the sandbox, git operations sometimes fail with unlink: Operation not permitted on .git/objects/*/tmp_obj_* files, confirming the sandbox cannot delete files it created.

Root cause (diagnosed)

Git's atomic object write sequence:

  1. open(tmp_obj, O_CREAT|O_WRONLY) → succeeds
  2. write compressed object data → succeeds
  3. fchmod(fd, 0444) → succeeds
  4. link(tmp_obj, <sha1_hash>) → succeeds (hard-link count → 2; named object exists)
  5. unlink(tmp_obj)FAILS with EPERM

The named object is written correctly (confirmed by hard-link count = 2 on every orphaned file). Only the cleanup of the tmp name fails. The com.apple.Virtualization.VirtualMachine.xpc sandbox policy permits open(O_CREAT) and link() on bind-mounted host paths but not unlink(). The same mechanism leaves in-progress lock files behind when a session VM is killed mid-operation.

Evidence

  • 81 orphaned tmp_obj_* files found across 5 repos after normal Cowork usage (oldest 6 days, all nlink=2)
  • 6 stale .lock files across 4 repos (oldest 27 days)
  • lsof confirms only com.apple.Virtualization.VirtualMachine (PID varies per session) holds open handles into .git/
  • No macOS immutable flags (chflags) or blocking extended attributes on any of the affected files
  • ls -laO on .git/ shows - flags throughout; only com.apple.provenance xattr on .git/index (harmless)
# Sample: named object and stranded tmp name are the same inode
.git/objects/3b/
  -r--r--r--  2  tonypurkins  7fb24114514b5d7c324bc88eca2f0f79694f26   ← named object
  -r--r--r--  2  tonypurkins  tmp_obj_IRVfqf                            ← stranded tmp, same inode

Workaround deployed (user-side)

Host-side launchd agent running every 300 s removes tmp_obj_* files older than 300 s with nlink ≥ 2, and .lock files older than 300 s. This is a host-side patch for a sandbox-side bug.

Suggested fix

The virtiofs implementation in com.apple.Virtualization.VirtualMachine.xpc should permit unlink() on files created by the guest process in a bind-mounted host directory. Alternatively, Cowork could run a post-session cleanup hook on the host that removes any tmp_obj_* and .lock files left behind in bind-mounted repos.

Reported by

Cowork user Beardy-Man (Data Argo studio). Diagnosed with Claude Code (claude-sonnet-4-6) on 2026-05-26.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING