claude-code - 💡(How to fix) Fix Claude.app: CCD subprocess fails with EACCES on shared /tmp/claude-settings-*.json across macOS users [2 comments, 2 participants]

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…
GitHub stats
anthropics/claude-code#52505Fetched 2026-04-24 06:05:24
View on GitHub
Comments
2
Participants
2
Timeline
8
Reactions
0
Timeline (top)
labeled ×4commented ×2closed ×1cross-referenced ×1

When two macOS user accounts (fast user switching) are simultaneously running Claude.app, the Claude Code CCD subprocess fails to start for the second user with exit code 1 and no stdout. The UI reports Claude Code process exited with code 1 / hadFirstResponse=false / reason=no_response immediately after sending any message.

Root cause: Claude Code caches the parsed --settings argument in /tmp/claude-settings-<hash>.json. The hash is derived only from the --settings input, not the uid. When both Claude.app instances pass the same --settings value (both pass --settings {} by default), they collide on the same path. Because /tmp has the macOS sticky bit, whichever user created the file first owns it and the other user cannot overwrite or unlink it. The subprocess exits before emitting any output.

Error Message

In Claude.app for the second user:

Root Cause

Root cause: Claude Code caches the parsed --settings argument in /tmp/claude-settings-<hash>.json. The hash is derived only from the --settings input, not the uid. When both Claude.app instances pass the same --settings value (both pass --settings {} by default), they collide on the same path. Because /tmp has the macOS sticky bit, whichever user created the file first owns it and the other user cannot overwrite or unlink it. The subprocess exits before emitting any output.

Fix Action

Fix / Workaround

Workarounds

Code Example

[error] Session <id> query error: Claude Code process exited with code 1
      at sIr.getProcessExitError (.vite/build/index.js:390:8041)
      at ChildProcess.i (.vite/build/index.js:390:11086)
  [info] [CCD CycleHealth] unhealthy cycle for <id> (0s, hadFirstResponse=false, reason=no_response)

---

BUNDLE="$HOME/Library/Application Support/Claude/claude-code/2.1.111/claude.app/Contents/MacOS/claude"
SP="$HOME/Library/Application Support/Claude/local-agent-mode-sessions/skills-plugin/<org-uuid>/<session-uuid>"

printf '%s\n' '{"type":"user","message":{"role":"user","content":"hi"}}' | \
  "$BUNDLE" \
    --output-format stream-json --verbose --input-format stream-json \
    --effort xhigh --model 'claude-opus-4-7[1m]' \
    --permission-prompt-tool stdio \
    --allowedTools 'mcp__computer-use,mcp__ccd_session__spawn_task,mcp__ccd_session__mark_chapter' \
    --setting-sources=user,project,local \
    --permission-mode acceptEdits \
    --allow-dangerously-skip-permissions \
    --include-partial-messages \
    --plugin-dir "$SP" \
    --replay-user-messages \
    --settings '{}'
; echo "EXIT=$?"

---

EXIT=1
stdout: (empty)
stderr: Error processing settings: EACCES: permission denied, open '/tmp/claude-settings-44136fa355b3678a.json'

---

$ ls -la /tmp/claude-settings-44136fa355b3678a.json
-rw-r--r--  1 Haven  wheel  2  Apr 23 14:18  /tmp/claude-settings-44136fa355b3678a.json

$ cat /tmp/claude-settings-44136fa355b3678a.json
{}

$ ls -ld /tmp
lrwxr-xr-x  1 root  wheel  11  /tmp -> private/tmp         # sticky bit on /private/tmp

---

/Applications/Claude.app/Contents/Helpers/disclaimer \
  /Users/Haven/Library/Application Support/Claude/claude-code/2.1.111/claude.app/Contents/MacOS/claude \
  --output-format stream-json --verbose --input-format stream-json \
  --effort xhigh --model claude-opus-4-7[1m] \
  --permission-prompt-tool stdio \
  --allowedTools mcp__computer-use,mcp__ccd_session__spawn_task,mcp__ccd_session__mark_chapter \
  --setting-sources=user,project,local \
  --permission-mode acceptEdits --allow-dangerously-skip-permissions \
  --include-partial-messages \
  --plugin-dir /Users/Haven/Library/Application Support/Claude/local-agent-mode-sessions/skills-plugin/<org>/<sess> \
  --replay-user-messages \
  --settings {}
RAW_BUFFERClick to expand / collapse

Claude Code: /tmp/claude-settings-*.json collision across macOS users

Summary

When two macOS user accounts (fast user switching) are simultaneously running Claude.app, the Claude Code CCD subprocess fails to start for the second user with exit code 1 and no stdout. The UI reports Claude Code process exited with code 1 / hadFirstResponse=false / reason=no_response immediately after sending any message.

Root cause: Claude Code caches the parsed --settings argument in /tmp/claude-settings-<hash>.json. The hash is derived only from the --settings input, not the uid. When both Claude.app instances pass the same --settings value (both pass --settings {} by default), they collide on the same path. Because /tmp has the macOS sticky bit, whichever user created the file first owns it and the other user cannot overwrite or unlink it. The subprocess exits before emitting any output.

Environment

  • macOS 26.4.1 (25E253), Apple Silicon (Mac17,8)
  • Claude.app 1.3883.0
  • Bundled Claude Code 2.1.111 at /Users/<user>/Library/Application Support/Claude/claude-code/2.1.111/claude.app/Contents/MacOS/claude
  • Two macOS user accounts logged in via fast user switching, each running Claude.app

Observed behavior

In Claude.app for the second user:

  • Every new conversation immediately shows Claude Code process exited with code 1
  • No assistant response renders (hadFirstResponse=false, reason=no_response)
  • ~/Library/Logs/Claude/main.log shows repeated:
    [error] Session <id> query error: Claude Code process exited with code 1
        at sIr.getProcessExitError (.vite/build/index.js:390:8041)
        at ChildProcess.i (.vite/build/index.js:390:11086)
    [info] [CCD CycleHealth] unhealthy cycle for <id> (0s, hadFirstResponse=false, reason=no_response)
  • Cowork VM sessions (different spawn path: Using Claude VM spawn function) are unaffected.
  • The bundled binary works fine when invoked standalone from a terminal.

Reproduction

Two macOS users logged in simultaneously (fast user switching). Each user launches Claude.app and tries to start a new conversation.

Minimal reproduction of the underlying failure, using the exact spawn args Claude.app uses (captured via ps -A -o user,pid,ppid,command):

BUNDLE="$HOME/Library/Application Support/Claude/claude-code/2.1.111/claude.app/Contents/MacOS/claude"
SP="$HOME/Library/Application Support/Claude/local-agent-mode-sessions/skills-plugin/<org-uuid>/<session-uuid>"

printf '%s\n' '{"type":"user","message":{"role":"user","content":"hi"}}' | \
  "$BUNDLE" \
    --output-format stream-json --verbose --input-format stream-json \
    --effort xhigh --model 'claude-opus-4-7[1m]' \
    --permission-prompt-tool stdio \
    --allowedTools 'mcp__computer-use,mcp__ccd_session__spawn_task,mcp__ccd_session__mark_chapter' \
    --setting-sources=user,project,local \
    --permission-mode acceptEdits \
    --allow-dangerously-skip-permissions \
    --include-partial-messages \
    --plugin-dir "$SP" \
    --replay-user-messages \
    --settings '{}'
; echo "EXIT=$?"

Output when the other user already owns the cache file:

EXIT=1
stdout: (empty)
stderr: Error processing settings: EACCES: permission denied, open '/tmp/claude-settings-44136fa355b3678a.json'

State of the blocking file:

$ ls -la /tmp/claude-settings-44136fa355b3678a.json
-rw-r--r--  1 Haven  wheel  2  Apr 23 14:18  /tmp/claude-settings-44136fa355b3678a.json

$ cat /tmp/claude-settings-44136fa355b3678a.json
{}

$ ls -ld /tmp
lrwxr-xr-x  1 root  wheel  11  /tmp -> private/tmp         # sticky bit on /private/tmp

The hash 44136fa355b3678a is deterministic for --settings {}, so every Claude.app spawn with default settings collides on the same file regardless of user.

Why the spawn ends up with this arg

Claude.app always passes --settings '{}' to the bundled binary (confirmed in the ps dump of the live process tree):

/Applications/Claude.app/Contents/Helpers/disclaimer \
  /Users/Haven/Library/Application Support/Claude/claude-code/2.1.111/claude.app/Contents/MacOS/claude \
  --output-format stream-json --verbose --input-format stream-json \
  --effort xhigh --model claude-opus-4-7[1m] \
  --permission-prompt-tool stdio \
  --allowedTools mcp__computer-use,mcp__ccd_session__spawn_task,mcp__ccd_session__mark_chapter \
  --setting-sources=user,project,local \
  --permission-mode acceptEdits --allow-dangerously-skip-permissions \
  --include-partial-messages \
  --plugin-dir /Users/Haven/Library/Application Support/Claude/local-agent-mode-sessions/skills-plugin/<org>/<sess> \
  --replay-user-messages \
  --settings {}

So the collision affects every new Claude.app conversation for the second user, not just edge cases.

Expected behavior

Any of the following would fix it:

  1. Namespace the cache path by uid, e.g. /tmp/claude-settings-<uid>-<hash>.json.
  2. Use $TMPDIR instead of /tmp — on macOS this is already per-user (/var/folders/.../T/), which is the correct location for per-user scratch files.
  3. If the target file exists and is not owned by the current user, fall through to a uid-suffixed fallback path instead of failing.
  4. At minimum, surface the EACCES error to the Claude.app UI instead of collapsing it into a generic "process exited with code 1".

$TMPDIR (option 2) is the standard macOS behavior and is likely the smallest correct change.

Workarounds

  • Only run Claude.app in one macOS user at a time.
  • If both users are active, the blocked user can run sudo rm /tmp/claude-settings-*.json and relaunch Claude.app — but the file will be recreated by the other user's Claude.app as soon as it spawns a CCD subprocess, so this recurs.

Signals that narrow the search for anyone hitting this

  • Exit code 1 with zero stdout, hadFirstResponse=false, reason=no_response.
  • Standalone invocation of the bundled binary works; Claude.app invocation does not.
  • Cowork VM sessions work (they use a different spawn code path).
  • Another macOS user is logged in concurrently (dscl . -list /Users shows more than one non-system user, and ps -A -o user shows Claude processes under a uid other than yours).
  • ls -la /tmp/claude-settings-*.json shows files owned by a different user.

extent analysis

TL;DR

The most likely fix is to use the $TMPDIR environment variable instead of /tmp for caching settings to avoid collisions between users.

Guidance

  1. Verify the issue: Check if the problem occurs when two macOS users run Claude.app simultaneously and the second user's Claude Code process exits with code 1.
  2. Check cache file ownership: Run ls -la /tmp/claude-settings-*.json to see if the cache file is owned by a different user, causing the collision.
  3. Use $TMPDIR: Modify the Claude Code to use $TMPDIR instead of /tmp for caching settings, which is the standard macOS behavior for per-user scratch files.
  4. Test the fix: After applying the fix, run Claude.app with two users simultaneously to verify that the issue is resolved.

Example

No code snippet is provided as the issue is more related to the environment and configuration rather than a specific code fix.

Notes

The issue is specific to macOS and the use of /tmp for caching settings. Using $TMPDIR is the recommended solution as it is the standard way to handle per-user temporary files on macOS.

Recommendation

Apply the workaround by using $TMPDIR instead of /tmp for caching settings, as it is the smallest correct change and aligns with standard macOS behavior.

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…

FAQ

Expected behavior

Any of the following would fix it:

  1. Namespace the cache path by uid, e.g. /tmp/claude-settings-<uid>-<hash>.json.
  2. Use $TMPDIR instead of /tmp — on macOS this is already per-user (/var/folders/.../T/), which is the correct location for per-user scratch files.
  3. If the target file exists and is not owned by the current user, fall through to a uid-suffixed fallback path instead of failing.
  4. At minimum, surface the EACCES error to the Claude.app UI instead of collapsing it into a generic "process exited with code 1".

$TMPDIR (option 2) is the standard macOS behavior and is likely the smallest correct change.

Still need to ship something?

×6

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

Back to top recommendations

TRENDING