Skip to content

fix(mcp): fall back to tmpdir socket on filesystems without AF_UNIX support#998

Open
zengwenliang416 wants to merge 1 commit into
colbymchenry:mainfrom
zengwenliang416:fix/daemon-enotsup-exfat-997
Open

fix(mcp): fall back to tmpdir socket on filesystems without AF_UNIX support#998
zengwenliang416 wants to merge 1 commit into
colbymchenry:mainfrom
zengwenliang416:fix/daemon-enotsup-exfat-997

Conversation

@zengwenliang416

Copy link
Copy Markdown

Summary

Fixes #997.

getDaemonSocketPath() now probes whether the target directory supports Unix domain sockets before returning an in-project path. On filesystems that don't support AF_UNIX (ExFAT, NTFS-3G, some FUSE mounts), it transparently falls back to the os.tmpdir() hash-based socket — the same path already used for the long-path case.

Problem

When a project lives on an ExFAT-formatted external volume (common on macOS for USB drives), the daemon fails to start:

✗ Failed to start server: listen ENOTSUP: operation not supported on socket /Volumes/drive/project/.codegraph/daemon.sock

The existing tmpdir fallback only triggered for paths exceeding 100 characters. Short paths on unsupported filesystems had no fallback.

Approach

  • Added canSocketInDir(dir) to daemon-paths.ts that spawns a short-lived child process (execFileSync) to attempt binding a Unix socket in the target directory
  • Result is cached per device number (fs.statSync().dev) so the probe runs at most once per mounted filesystem per process lifetime
  • Integrated into getDaemonSocketPath() alongside the existing length check
  • Both daemon and proxy call getDaemonSocketPath(), so they automatically agree on the socket path — no changes needed in daemon.ts or index.ts

Changes

  • src/mcp/daemon-paths.ts: Added canSocketInDir(), clearSocketSupportCache() (test helper), updated getDaemonSocketPath() guard
  • __tests__/daemon-socket-probe.test.ts: New test file covering probe behavior and cache semantics

Test plan

  • npm run build — compiles cleanly
  • New tests pass: canSocketInDir returns true on tmpdir, caches results, handles nonexistent dirs
  • Existing daemon-bind-failure.test.ts still passes (no regression)
  • Existing proxy-connect.test.ts and daemon-registry.test.ts still pass
  • Manual verification: getDaemonSocketPath('/Volumes/exfat-drive/project') returns tmpdir path; local APFS projects still get in-project path

…upport (colbymchenry#997)

ExFAT, NTFS-3G, and some FUSE-backed volumes do not support Unix domain
sockets — `listen()` fails with ENOTSUP. `getDaemonSocketPath` already
had a tmpdir fallback for long paths; this extends it to also probe
socket support via a short-lived child process, cached per device.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

Daemon fails with ENOTSUP on ExFAT / external volumes (no tmpdir fallback for unsupported socket)

1 participant