A project kept on an ExFAT/FAT external volume (or some network mounts /
WSL2 DrvFs) broke the background auto-sync daemon at two points, both
because the filesystem lacks POSIX features the daemon relied on:
1. Lock acquisition hard-links a temp file onto .codegraph/daemon.pid for
race-free exclusivity (#411) — these filesystems have no hard links.
2. The Unix-domain socket listen() fails regardless of path length, so the
old length-only tmpdir fallback never triggered.
Both surface as a capability error, but each OS reports a DIFFERENT errno
for the same gap (macOS ENOTSUP, Linux EPERM, Windows EISDIR), so the fix
is policy-based rather than an enumerated code-set:
- Lock: fall back to an O_EXCL create on any non-EEXIST link error. The
temp write already proved the directory is writable, so the fallback
either succeeds (still atomic + exclusive, "first writer wins") or
surfaces its own genuine error.
- Socket: an ordered candidate list [in-project, tmpdir] walked by BOTH
the daemon (binds) and the proxy (connects) — they converge on the
fallback with zero coordination. Relocate past any non-EADDRINUSE bind
error; EADDRINUSE still rethrows, preserving the #974 contract.
Normal repos are unaffected: the in-project candidate binds first, and the
hard-link lock path is unchanged.
Validated end-to-end on real removable-drive filesystems: macOS ExFAT
(hdiutil image), Linux FAT32 (Docker loop mount), Windows exFAT (diskpart
VHD) — each acquires the lock, relocates (or binds a named pipe on
Windows), and serves a real client.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>