[Bug] v2.1.117 regression: parallel Bash tool calls corrupt fd 3 in nested-Docker sandbox; permanent /proc/self/fd/3: Permission denied

Resolved 💬 10 comments Opened Apr 22, 2026 by jmmgreg Closed Apr 23, 2026

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/3 for 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.

View original on GitHub ↗

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