[BUG] Sandbox TMPDIR /tmp/claude not created — ENOENT after fresh boot

Resolved 💬 2 comments Opened Apr 9, 2026 by codename-cn Closed Apr 9, 2026

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

  1. rm -rf /tmp/claude (or reboot a system with tmpfs /tmp)
  2. Start Claude Code with sandbox enabled (e.g., via SDK with --permission-mode dontAsk)
  3. Run a Bash tool that uses $TMPDIR (e.g., any command that calls mktemp, or a Python/Node script using tempfile.mkdtemp() / fs.mkdtemp())
  4. Observe ENOENT error

Root cause in the binary (v2.1.97):

  1. Env setup sets TMPDIR=/tmp/claude (default):

``js
["SANDBOX_RUNTIME=1",
TMPDIR=${process.env.CLAUDE_TMPDIR || "/tmp/claude"}]
``

  1. Default write allowlist includes /tmp/claude:

``js
["/dev/stdout", "/dev/stderr", ..., "/tmp/claude", "/private/tmp/claude", ...]
``

  1. Linux sandbox setup silently drops missing paths:

``js
if (!fs.existsSync(path)) {
log(
[Sandbox Linux] Skipping non-existent write path: ${path});
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.

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗