[Bug] v2.1.117 regression: parallel Bash tool calls corrupt fd 3 in nested-Docker sandbox; permanent /proc/self/fd/3: Permission denied
Summary
In Claude Code 2.1.117, when running claude -p "..." inside a Docker container with the per-Bash sandbox enabled, multiple Bash tool calls issued in parallel within a single turn corrupt file descriptor 3 in the inner sandbox wrapper. The first parallel call fails:
Exit code 126
/bin/bash: line 4: /proc/self/fd/3: Permission denied
Other parallel calls in the same turn are cancelled by Claude as "parallel tool call errored". Every subsequent Bash call in the session — including a trivial echo "test" — also fails with the same fd/3 error, permanently disabling the Bash tool. Other tools (Read, Edit, Glob, Grep, Agent, MCP) keep working.
Sequential Bash works. Multiple Reads/Globs/MCP calls in parallel work. Bug is specific to parallel Bash + the inner per-Bash sandbox wrapper.
Pinning to 2.1.116 makes the bug disappear. Same Docker image, same sandbox-settings.json, only the CLI version differs.
Versions
- Affected: 2.1.117 (released 2026-04-22 00:04 UTC)
- Last known-good: 2.1.116 (released 2026-04-20)
- Platform tested: Linux arm64 inside Docker; Docker Desktop on macOS Apple Silicon host. Not tested on bare Linux.
Reproduction
1. Build a minimal image
Dockerfile:
FROM node:20-slim
RUN apt-get update && apt-get install -y --no-install-recommends \
curl ca-certificates bash bubblewrap socat \
&& rm -rf /var/lib/apt/lists/*
RUN curl -fsSL https://claude.ai/install.sh | bash
ENV PATH="/root/.local/bin:$PATH"
docker build -t fd3-repro .
2. Sandbox config
sandbox-settings.json:
{
"sandbox": {
"enabled": true,
"enableWeakerNestedSandbox": true,
"failIfUnavailable": true,
"autoAllowBashIfSandboxed": true,
"allowUnsandboxedCommands": false,
"network": {"allowedDomains": []},
"filesystem": {"allowWrite": ["/tmp"]}
}
}
(enableWeakerNestedSandbox: true is required inside Docker — without it, bwrap fails with Creating new namespace failed: Operation not permitted.)
3. Run
docker run --rm \
--cap-add NET_ADMIN --security-opt seccomp=unconfined \
-v "$PWD/sandbox-settings.json:/sandbox-settings.json:ro" \
-e CLAUDE_CODE_OAUTH_TOKEN=<your-token> \
fd3-repro \
claude -p 'TURN 1: Run ONE Bash call: { echo hello | sed "s/./X/g" ; echo world 2>/dev/null ; }
TURN 2: In ONE response, issue FOUR parallel Bash tool calls — all four at once, not sequentially:
a) echo first
b) echo second
c) echo third
d) echo fourth
TURN 3: Run: echo after_parallel
Report each result verbatim.' \
--output-format stream-json \
--permission-mode dontAsk \
--allowed-tools Bash \
--settings /sandbox-settings.json
(The Bash commands inside don't need network — I switched the parallel batch from curl to echo so the repro doesn't depend on any reachable host. The bug fires inside the sandbox wrapper before the user command runs.)
Observed
- TURN 1 (single complex Bash): ✅ succeeds — output
XXXXX\nworld - TURN 2 (4 parallel echoes): ❌ first fails with
Exit code 126 / /bin/bash: line 4: /proc/self/fd/3: Permission denied. Other 3 cancelled as "parallel tool call errored". - TURN 3 (
echo after_parallel): ❌ same fd/3 error.
Expected
All 4 parallel Bash calls execute (or are queued); TURN 3 runs cleanly.
What I haven't isolated
- Whether the prior single Bash in TURN 1 is necessary, or whether the bug also fires on the very first parallel batch with no prior Bash. A separate test with 3 parallel Bash calls and no prior Bash passed (no fd/3 error). So it could be the count threshold (≥4), the prior Bash, an interaction with the specific commands, or timing. Filing what I've reproduced deterministically.
Workaround
RUN curl -fsSL https://claude.ai/install.sh | bash -s -- 2.1.116
Possibly related
- 2.1.113 introduced the switch from "bundled JS" to "native Claude Code binary" per its release notes. The native binary's sandbox wrapper appears to open
/proc/self/fd/3for some control channel; 2.1.117 is the first version where parallel Bash + the nested-Docker sandbox combine pathologically. - #47909 — gradual fd leak in long macOS sessions. Different surface (gradual, macOS, not parallel-triggered) but same general fd-management area.
This issue has 10 comments on GitHub. Read the full discussion on GitHub ↗