[BUG] bwrap sandbox broken on merged-usr systems (Arch): "Can't mount tmpfs on /newroot/lib64" — enableWeakerNestedSandbox does not fix it, MCP servers fail to start
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
On Arch Linux (and any distro using merged-usr where /lib64 is a symlink), the bwrap sandbox fails unconditionally with:
bwrap: Can't mount tmpfs on /newroot/lib64: No such file or directory
This is because /lib64 is a symlink (/lib64 -> usr/lib) and bwrap tries to mount a tmpfs on the symlink target path before resolving it, which fails. Setting enableWeakerNestedSandbox: true does not fix this — the error persists. As a result, MCP servers cannot start at all (they are spawned by Claude Code at startup via the sandbox), and /mcp is unusable.
What Should Happen?
Sandbox starts successfully. Either bwrap uses --symlink usr/lib /lib64 instead of trying to bind-mount /lib64 directly, or enableWeakerNestedSandbox resolves symlinks before constructing the sandbox filesystem.
Error Messages/Logs
bwrap: Can't mount tmpfs on /newroot/lib64: No such file or directory
Steps to Reproduce
Use Arch Linux or any merged-usr distro where /lib64 is a symlink:
Claude Model
Sonnet (default)
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.160
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
Other
Additional Information
_No response_
Showing cached comments. Read the full discussion on GitHub ↗
5 Comments
Similar issue with sandboxing on Ubuntu 22.04/v2.1.167, any attempt at file access such as
!lsfails withbwrap: Can't mount tmpfs on /newroot/lib: No such file or directoryeven when it's done within the .claude/settings.json specified folders. Using bubblewrap 0.6.1.Corroborating with a fresh data point: this also reproduces on Ubuntu 26.04 (merged-usr) with Claude Code 2.1.168 — i.e. it's not specific to 22.04 or one CC version.
Symptom: every Bash tool call — including
trueandecho hello— returns exit code 1 with no stdout/stderr. File-read tools are unaffected; only the sandboxed Bash layer is dead. (Same error class @jonasced reported:bwrap: Can't mount tmpfs on /newroot/lib….)Environment: Ubuntu 26.04 (KVM VM), bubblewrap 0.11.1, socat installed, run with
--dangerously-skip-permissions.The host itself is fully sandbox-capable — direct bwrap succeeds for every namespace:
…so it's Claude Code's specific sandbox invocation failing on merged-usr (where
/lib64→/usr/lib64is a symlink), not a kernel/namespace restriction on the host.Workarounds that do NOT fix it:
usernsprofile from #17727sandbox.enabled: false(silently ignored on Linux — see #35986)enableWeakerNestedSandbox: true(as already noted in the OP)socatImpact: completely blocks Bash for every Claude Code agent on the host — no build/test/commit possible. It also compounds with #17374 (sandbox fails in git worktrees), which is the common layout for worktree-based multi-agent setups.
Since merged-usr is the default on modern Ubuntu/Fedora/Arch, this likely hits a large share of Linux-server users. Happy to provide more diagnostics. 🙏
On Arch with Claude CLI 2.1.177 I'm still seeing:
So a variant of the error from the OP, but
binalways fails (first) rather thanlib64, which is strange given that it's the same system, but likely the same issue anyway.FWIW, for me this does work around it. Of course this results in no sandboxing being applied, but it allows me to use Claude CLI for now. If I set that to
trueI immediately get the issue again.@bcherny any chance this gets priotized as disabling sandbox is not an option.
Workaround: bwrap wrapper script for usrmerge systems
(Since my English isn't great, I had Claude Code review the diff and write this message for me.)
Confirmed on Ubuntu 24.04 inside a Docker dev container (same usrmerge layout where
/bin,/lib,/lib64,/sbinare symlinks tousr/*).There are two failure modes on usrmerge:
--tmpfs /bin(and/lib,/lib64, etc.) — bwrap tries to create a mount point on the symlink path before mounting; fails with "No such file or directory"--tmpfs /usr— blanks the entire/usrtree, so/bin/bash→/usr/bin/bash→ gone; bwrap exits withexecvp /bin/bash: No such file or directoryWorkaround
Install a thin wrapper at the path Claude Code calls as
bwrap(configurable viamanaged-settings.json'ssandbox.bwrapPath). The wrapper transforms the args before passing them to the real binary:--tmpfs <usrmerge-path>(e.g./bin,/lib,/lib64): replaces it with--symlink usr/bin /bin(preserving the symlink structure instead of trying to mount tmpfs on the symlink destination)--tmpfs /usr: keeps--tmpfs /usrand immediately injects--dir /usr/bin --ro-bind /usr/bin /usr/bin(andlib,lib64,lib32,sbin) to restore the real contents after blanking/usr/bin/bwrap(wrapper):Setup steps:
The root fix in Claude Code would be to emit
--symlink usr/bin /bin(etc.) instead of--tmpfs /binwhen the target is a symlink on the host, and to rebind/usr/binetc. after any--tmpfs /usr. Hope this helps narrow down the fix.P.S. This workaround is just a temporary fix, so I'll be looking forward to an official patch.