[BUG] Sandbox TMPDIR /tmp/claude not created — ENOENT after fresh boot
What's Wrong?
Claude Code hardcodes TMPDIR=/tmp/claude for sandboxed subprocesses and adds /tmp/claude to its default bubblewrap write allowlist, but does not create the directory on the host. After a fresh boot (or any tmpfs clear), /tmp/claude does not exist, and bwrap silently skips the bind mount. Every tempfile/mkdtemp call inside the sandbox then fails with ENOENT.
This is a latent/flaky issue: it only manifests when /tmp/claude is missing (e.g., after reboot). Once any Claude Code session has run and incidentally created it, subsequent sessions work fine — until the next reboot.
What Should Happen?
Claude Code should ensure /tmp/claude exists on the host before spawning the bubblewrap sandbox, so the bind mount succeeds and TMPDIR is usable inside sandboxed subprocesses.
Error Messages/Logs
Real-world trigger: Playwright's node.js driver calls fs.mkdtemp(path.join(os.tmpdir(), "playwright-artifacts-")) inside the sandbox:
playwright._impl._errors.Error: BrowserType.launch_persistent_context:
ENOENT: no such file or directory, mkdtemp '/tmp/claude/playwright-artifacts-xxxxxx'
Minimal trigger inside the sandbox:
$ mktemp -d
mktemp: failed to create directory via template '/tmp/claude/tmp.XXXXXXXXXX': No such file or directory
Relevant debug-level log from the binary (not surfaced to user):
[Sandbox Linux] Skipping non-existent write path: /tmp/claude
Steps to Reproduce
rm -rf /tmp/claude(or reboot a system with tmpfs/tmp)- Start Claude Code with sandbox enabled (e.g., via SDK with
--permission-mode dontAsk) - Run a Bash tool that uses
$TMPDIR(e.g., any command that callsmktemp, or a Python/Node script usingtempfile.mkdtemp()/fs.mkdtemp()) - Observe ENOENT error
Root cause in the binary (v2.1.97):
- Env setup sets
TMPDIR=/tmp/claude(default):
``jsTMPDIR=${process.env.CLAUDE_TMPDIR || "/tmp/claude"}
["SANDBOX_RUNTIME=1", ]``
- Default write allowlist includes
/tmp/claude:
``js``
["/dev/stdout", "/dev/stderr", ..., "/tmp/claude", "/private/tmp/claude", ...]
- Linux sandbox setup silently drops missing paths:
``js[Sandbox Linux] Skipping non-existent write path: ${path}
if (!fs.existsSync(path)) {
log();``
continue; // bind mount never created, but TMPDIR still set
}
Is this a regression?
I don't know
Claude Code Version
2.1.97 (Claude Code)
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
WSL (Windows Subsystem for Linux)
Additional Information
Workaround: Parent process creates the directory before spawning Claude Code:
Path("/tmp/claude").mkdir(exist_ok=True)
Python's tempfile module has fallback logic and eventually creates temp files in cwd when TMPDIR is invalid — which is arguably worse than crashing, as it silently pollutes the project workspace with temp state.
macOS (seatbelt sandbox) may behave differently — this report is Linux/bwrap only.
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗