Background jobs stamped with stale/non-existent originCwd from the open project tab (not terminal cwd), causing opaque "working directory no longer exists" startup failures
Summary
Claude Code stamps background (daemon) jobs with the originCwd of the currently-displayed project tab at submission time. It does not read the terminal's process.cwd(), and it does not validate that the path still exists. Once a project whose directory lives under /private/tmp (or any ephemeral/removable path) is registered, every subsequent background job submitted from that tab inherits the same path. When macOS later purges /private/tmp, those jobs fail to start with:
Session can't start — working directory no longer exists: /private/tmp/<dir>
Impact
- Background jobs become unstartable through no fault of the user. The failure is opaque ("working directory no longer exists") and gives no hint that the cwd was inherited from a stale project tab rather than the terminal's actual working directory.
- Unrelated, later jobs submitted from the same tab all silently inherit the dead path.
- The stale project key persists in
~/.claude.json, so re-selecting the old tab re-triggers the failure indefinitely.
Steps to reproduce
- Open/launch a Claude Code session whose working directory is under
/private/tmp(e.g. a scratch/verify dir). This registers a project key for that path in~/.claude.json. - From that project tab, submit one or more background jobs. They are stamped with
originCwd = /private/tmp/<dir>. - Let macOS purge
/private/tmp(reboot, or the ~3-day periodic/tmpcleanup). - The background jobs now fail to start with
Session can't start — working directory no longer exists: /private/tmp/<dir>, even for jobs whose intent has nothing to do with that directory.
Root cause (observed)
The cwd written into each job comes from app/UI project state, not the terminal. The binary exposes app-level setCwdState/getCwdState and an originCwd field that are independent of process.cwd(). originCwd is persisted into the job's state.json and used for chdir at startup, with no existence check, and the originating project key is never pruned from ~/.claude.json when its directory disappears.
Expected behavior
When creating/launching a background job, Claude Code should:
- Validate that
originCwdexists before writing it into the job'sstate.json/ beforechdir. - If the path is gone, fall back to
$HOME(or the nearest existing ancestor) and surface a clear, recoverable message rather than a hard startup failure. - Optionally, prune project keys in
~/.claude.jsonwhose directories no longer exist.
Environment
- Claude Code
2.1.162(~/.local/bin/claude,~/.local/share/claude/versions/2.1.162), daemon-backed background jobs. - macOS (Darwin 25.6.0).
Workaround
Don't launch Claude sessions from /private/tmp (purged on reboot / ~3-day periodic cleanup); use a persistent directory. To recover, with the app quit: remove the stale project key from ~/.claude.json and delete the orphaned ~/.claude/jobs/<id> records. A small status/prune doctor script that scans jobs for a missing originCwd and prunes ~/.claude.json project keys whose directory no longer exists makes this repeatable.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗