[BUG] Sandbox: pnpm hangs forever when the project pins another pnpm version, and the write denial is never reported
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 macOS, with the Bash sandbox on, every pnpm command hangs forever (even pnpm --version) in a project whose package.json pins a pnpm version that differs from the installed one. That happens through packageManager or through devEngines.packageManager with onFail: "download".
The cause is a filesystem write denial:
- To switch versions, pnpm 12 takes a directory lock at
~/Library/pnpm/package-manager-store/v11/tmp/engine-locks/pnpm@<version>.lock(mkdir style lock). ~/Library/pnpmis not in the sandbox write allowlist, somkdirfails withEPERM.- pnpm does not fail on
EPERM. It waits for the lock forever. This happens even when the wanted version is already in pnpm's local cache.
Two problems make this hard to work with in Claude Code:
- The denial is silent. A blocked network host shows up in a
<sandbox_violations>block. A blocked filesystem write shows nothing. The command just hangs until the Bash timeout, so neither the agent nor the user can tell that the sandbox caused it. It took manual work to find the cause: comparing versions, reading strings from the pnpm binary, and testingmkdirdirectly. - There is no sandboxed way out.
pnpm installneeds write access to the pnpm home (~/Library/pnpmon macOS) in any case. The only fallback isdangerouslyDisableSandbox, and auto mode correctly denies that. So the agent cannot run pnpm at all in such a project.
The endless wait on EPERM is pnpm's behavior and belongs in a separate pnpm report. This issue is about the Claude Code side: the denial is not reported, and the default write allowlist leaves out the package manager home.
What Should Happen?
- Filesystem write denials should be reported to the agent the same way network denials are (path and operation), at least when a command times out after one.
- Ideally, the sandbox should offer a documented way to allow common package manager homes and stores (
~/Library/pnpm,~/.local/share/pnpm,~/.npm,~/Library/Caches/pnpm), or the docs should name them as paths users usually need to add.
Error Messages/Logs
Steps to Reproduce
- Install pnpm 12.x (here: 12.5.1, the standalone native binary in
~/Library/pnpm). - In a temp directory, create
package.json:
``json``
{ "name": "repro", "devEngines": { "packageManager": { "name": "pnpm", "version": "12.8.0", "onFail": "download" } } }
- In a Claude Code session with the Bash sandbox on, have Claude run
pnpm --versionin that directory.
Result: the command hangs until the Bash timeout. No <sandbox_violations> output appears.
Checks done inside the sandbox:
| Case | Result |
|---|---|
| Pinned version equals the installed one (12.5.1) | Prints 12.5.1 at once |
| Pinned 12.8.0, onFail: "error" | Fails at once with ERR_PNPM_BAD_PM_VERSION |
| Pinned 12.7.0, 12.8.0 or 12.8.1 (all already in pnpm's cache), onFail: "download" | Hangs |
| Same, with allowed_domains: ["registry.npmjs.org"] | Hangs (network is not the cause) |
| pnpm without a version switch, network access | Works |
| python3 -c "os.mkdir('~/Library/pnpm/package-manager-store/v11/tmp/engine-locks/pnpm@12.7.0.lock')" | EPERM |
| PNPM_CONFIG_MANAGE_PACKAGE_MANAGER_VERSIONS=false pnpm --version | Works (runs 12.5.1, skips the switch) |
Workaround: add ~/Library/pnpm to sandbox.filesystem write paths, or set PNPM_CONFIG_MANAGE_PACKAGE_MANAGER_VERSIONS=false (pnpm then runs the installed version instead of the pinned one).
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.278 (desktop app, Code tab), auto mode, Bash sandbox on (default config)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_