claude-code - 💡(How to fix) Fix [BUG] Bash tool fails with /proc/self/fd/3: Permission denied after a few calls in 2.1.116 and 2.1.117 [2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#52118Fetched 2026-04-23 07:36:10
View on GitHub
Comments
2
Participants
2
Timeline
12
Reactions
0
Author
Timeline (top)
labeled ×5commented ×2cross-referenced ×2subscribed ×1

Error Message

The Bash tool should run the requested command and return its output. If the command fails for its own reasons (e.g. a real git error), that output should be returned. The wrapper preamble should not block execution by failing to open /proc/self/fd/3.

Error Messages/Logs

  1. From that point on, every Bash call in the session fails with the same /proc/self/fd/3: Permission denied error, including a bare true. Every Bash call since, including a bare true, has failed with the same fd-3 error.

Root Cause

  • The exact contents of the Bash tool's wrapper preamble, and how line 4 accesses /proc/self/fd/3 (source, exec <, cat, etc.).
  • Which specific bwrap operation in the launch path clears the dumpable flag (user namespace creation, capability drop, setuid transition, etc.).
  • Why 2.1.115 is missing from npm. It may have been unpublished intentionally, or never published. If it was pulled because of this regression, that would identify 2.1.115 as the bad release and 2.1.116 as inheriting the bug rather than introducing it.
  • What changed between 2.1.114 and 2.1.116 on the wrapper preamble and/or bwrap-launch path.

Fix Action

Fix / Workaround

  1. Install Claude Code 2.1.116 or 2.1.117: npm install -g @anthropic-ai/[email protected]
  2. Start a fresh Claude Code session in a WSL2 shell with the sandbox enabled.
  3. Issue a few trivial Bash tool calls (e.g., ls, pwd, echo). These succeed.
  4. Issue a slightly heavier call. In the most recent reproduction, the fifth call — cd /some/dir && git rev-parse --is-inside-work-tree 2>&1 — tripped the failure.
  5. From that point on, every Bash call in the session fails with the same /proc/self/fd/3: Permission denied error, including a bare true.
  6. Confirmed remediation: downgrade to 2.1.114 (npm install -g @anthropic-ai/[email protected]). Same reproducer is then clean.

A 2.6.22 kernel patch relaxed this for fd specifically, but the restriction still applies in containers, with certain capability changes, and with some syscalls (e.g. close_range).

  • proc(5) man page on /proc/[pid]/fd/ and the dumpable attribute.
  • Red Hat solution 36870, "A setuid root program is unable to access /proc/self/fd after it lowers its privileges to a normal user."
  • LKML thread "PROBLEM?: 'permission denied' when accessing /proc/self/fd/* after setuid" (kernel patch in 2.6.22).
  • Stack Overflow question 75558566, "Why is /proc/self/fd/n forbidden after setuid?"
  • containers/podman issue 10337, "Permission denied when container process executes close_range syscall" — same kernel mechanism in a container context.``

Code Example

Exit code 126
/bin/bash: line 4: /proc/self/fd/3: Permission denied

- Exit 126 = bash "permission denied — could not exec target."
- "line 4" is constant across every observed instance and is almost certainly inside an injected wrapper preamble (most user-supplied commands are a single line).
- The failing reference is /proc/self/fd/3 — whatever bash inherited as fd 3.
- Failure is independent of the user command (single command, compound with && / |, git, non-git, bare true).

---

ls -la /home/grault/planning/ 2>&1 | head -50
ls -la /home/grault/planning/applications/ 2>&1 | head -20

---

cd /home/grault/planning && git rev-parse --is-inside-work-tree 2>&1
ls -la /home/grault/planning/.git 2>&1 | head -3
test -d /home/grault/planning/.git && echo "git repo" || echo "not a git repo"
RAW_BUFFERClick to expand / collapse

Preflight Checklist

  • I have searched existing issues and this hasn't been reported yet
  • This is a single bug report (please file separate reports for different bugs)
  • I am using the latest version of Claude Code

What's Wrong?

The Bash tool succeeds on a small number of early calls per session, then transitions to a permanent-for-the-session failure where every subsequent Bash call — including a bare true — exits 126 with /bin/bash: line 4: /proc/self/fd/3: Permission denied. Once the failure starts in a session, it never recovers; only starting a new Claude Code process gets the small initial window of working calls back. The pattern reproduces in every session on 2.1.116 and 2.1.117 and is independent of command shape.

What Should Happen?

The Bash tool should run the requested command and return its output. If the command fails for its own reasons (e.g. a real git error), that output should be returned. The wrapper preamble should not block execution by failing to open /proc/self/fd/3.

Error Messages/Logs

Exit code 126
/bin/bash: line 4: /proc/self/fd/3: Permission denied

- Exit 126 = bash "permission denied — could not exec target."
- "line 4" is constant across every observed instance and is almost certainly inside an injected wrapper preamble (most user-supplied commands are a single line).
- The failing reference is /proc/self/fd/3 — whatever bash inherited as fd 3.
- Failure is independent of the user command (single command, compound with && / |, git, non-git, bare true).

Steps to Reproduce

  1. Install Claude Code 2.1.116 or 2.1.117: npm install -g @anthropic-ai/[email protected]
  2. Start a fresh Claude Code session in a WSL2 shell with the sandbox enabled.
  3. Issue a few trivial Bash tool calls (e.g., ls, pwd, echo). These succeed.
  4. Issue a slightly heavier call. In the most recent reproduction, the fifth call — cd /some/dir && git rev-parse --is-inside-work-tree 2>&1 — tripped the failure.
  5. From that point on, every Bash call in the session fails with the same /proc/self/fd/3: Permission denied error, including a bare true.
  6. Confirmed remediation: downgrade to 2.1.114 (npm install -g @anthropic-ai/[email protected]). Same reproducer is then clean.

Trigger pattern observed in the most recent test (2.1.116):

  • Calls 1–4 (parallel ls, pwd && whoami && uname -a, echo chain) → all succeeded.
  • Call 5 (cd … && git rev-parse) → tripped the failure.
  • Bare true immediately after → also failed.

Whether the trigger is tied to call count, to git invocation specifically, or to some other property of the fifth call has not been bisected.

The following do not restore the Bash tool: process restart, machine reboot, the prompt !cmd prefix (!cmd traverses the same Bash tool path as agent-issued tool calls, not the user's underlying terminal).

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

2.1.114 (2.1.115 unavailable in npm)

Claude Code Version

2.1.117 (also reproduced on 2.1.116)

Platform

Anthropic API

Operating System

Ubuntu/Debian Linux

Terminal/Shell

Windows Terminal

Additional Information

Hypothesis: kernel "dumpable" flag + wrapper accessing /proc/self/fd/3 inside a bwrap sandbox

Best fit for the observed behavior:

  1. The Bash tool wraps user commands in a bash script. Its preamble references /proc/self/fd/3 on line 4 — plausibly to source the user command from a pipe held open as fd 3 by the parent (source /proc/self/fd/3, exec < /proc/self/fd/3, or similar).
  2. The harness sandbox is bubblewrap (bwrap). Bwrap creates sandboxes via Linux user namespaces and can also drop capabilities or perform setuid-style transitions. Any of these clears the kernel's PR_SET_DUMPABLE flag on the bash subprocess.
  3. With dumpable = 0, /proc/<pid>/* is owned by root with restrictive permissions, and the bash subprocess cannot open /proc/self/fd/3. The open returns EACCES and bash exits 126 before running any user code.

A 2.6.22 kernel patch relaxed this for fd specifically, but the restriction still applies in containers, with certain capability changes, and with some syscalls (e.g. close_range).

This explains every observed symptom:

  • Per-session reproduction: the dumpable flag is per-process; each new bash invocation hits it fresh.
  • Identical "line 4" failure across every session: the same wrapper preamble runs every time.
  • Works for a few calls then breaks: plausibly two code paths in the Bash tool — a fast/warm path that does not drop privs, and a fuller path that does. Crossing into the second path is what breaks the session. Alternatively the early calls do not exercise the line-4 access (an early-return on a fast path); the first call that does is the one that visibly fails.
  • Survives reboot: the cause is wrapper code + sandbox-launch path, both of which load fresh in every new Claude Code process.
  • Began at 2.1.115 or 2.1.116: one of those two releases changed either the wrapper preamble or the bwrap-launch path in a way that exposes the dumpable interaction. 2.1.117 inherits the same bug.

I cannot directly inspect the wrapper preamble or the bwrap-launch path from inside the agent, so this is a strongly-supported hypothesis, not a verified diagnosis.

Open questions

  • The exact contents of the Bash tool's wrapper preamble, and how line 4 accesses /proc/self/fd/3 (source, exec <, cat, etc.).
  • Which specific bwrap operation in the launch path clears the dumpable flag (user namespace creation, capability drop, setuid transition, etc.).
  • Why 2.1.115 is missing from npm. It may have been unpublished intentionally, or never published. If it was pulled because of this regression, that would identify 2.1.115 as the bad release and 2.1.116 as inheriting the bug rather than introducing it.
  • What changed between 2.1.114 and 2.1.116 on the wrapper preamble and/or bwrap-launch path.

Related but distinct

#51126 — "[BUG] WSL2: Bash tool fails with E2BIG because Claude wraps bubblewrap in single /bin/bash -c string exceeding Linux MAX_ARG_STRLEN"

Same WSL2 platform and same bwrap sandbox layer, but a distinct failure mode and distinct affected versions:

  • #51126 fails at posix_spawn with E2BIG (argv > 128 KB), before bash ever runs.
  • This issue fails inside bash on line 4 of an injected wrapper preamble, with EACCES on /proc/self/fd/3.
  • #51126 is reported on 2.1.114, which is clean for this bug.
  • This bug is bounded to 2.1.115 or 2.1.116 (and inherited by 2.1.117).
  • #51126 only manifests when the bwrap deny-list is large enough to push the single -c argument past 128 KB; this bug triggers regardless of deny-list size, after a small number of calls.

Both likely stem from the bwrap-based sandbox layer's interaction with the existing Bash-tool wrapper, but they are independent failure modes triggered under different conditions.

Observed sessions

Session A

Pre-break (succeeded):

ls -la /home/grault/planning/ 2>&1 | head -50
ls -la /home/grault/planning/applications/ 2>&1 | head -20

Then everything subsequent failed identically:

cd /home/grault/planning && git rev-parse --is-inside-work-tree 2>&1
ls -la /home/grault/planning/.git 2>&1 | head -3
test -d /home/grault/planning/.git && echo "git repo" || echo "not a git repo"

Session B

Last working call: git add .claudeignore && git commit -m ... → returned [main 8521f16] chore(config): add .claudeignore.

First failing call (immediately after): git log --oneline -2 && echo --- && git status --short && echo --- && wc -l CLAUDE.md .claudeignore.

Every Bash call since, including a bare true, has failed with the same fd-3 error.

Sources for the kernel mechanism

  • proc(5) man page on /proc/[pid]/fd/ and the dumpable attribute.
  • Red Hat solution 36870, "A setuid root program is unable to access /proc/self/fd after it lowers its privileges to a normal user."
  • LKML thread "PROBLEM?: 'permission denied' when accessing /proc/self/fd/* after setuid" (kernel patch in 2.6.22).
  • Stack Overflow question 75558566, "Why is /proc/self/fd/n forbidden after setuid?"
  • containers/podman issue 10337, "Permission denied when container process executes close_range syscall" — same kernel mechanism in a container context.``

extent analysis

TL;DR

Downgrade to Claude Code version 2.1.114 to avoid the Bash tool failure caused by a permission denied error when accessing /proc/self/fd/3.

Guidance

  1. Verify the hypothesis: The failure is likely due to the PR_SET_DUMPABLE flag being cleared when the Bash tool drops privileges, causing the /proc/self/fd/3 access to fail.
  2. Check the wrapper preamble: Inspect the Bash tool's wrapper preamble to understand how it accesses /proc/self/fd/3 and consider modifying it to avoid this issue.
  3. Investigate bwrap-launch path: Examine the bwrap-launch path to determine which operation clears the dumpable flag and consider adjusting the sandbox configuration to prevent this.
  4. Test with different versions: Verify that downgrading to 2.1.114 resolves the issue and test other versions to identify the exact release that introduced the bug.

Example

No code snippet is provided as the issue is related to the interaction between the Bash tool, bwrap sandbox, and kernel mechanisms, and modifying the code without a clear understanding of the wrapper preamble and bwrap-launch path may not be effective.

Notes

The provided hypothesis is strongly supported but not verified, and further investigation is needed to confirm the root cause. The issue may be specific to the WSL2 platform and bwrap sandbox layer.

Recommendation

Apply the workaround by downgrading to Claude Code version 2.1.114, as it is confirmed to resolve the issue. This will allow users to continue using the Bash tool while the root cause is further investigated and a permanent fix is developed.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix [BUG] Bash tool fails with /proc/self/fd/3: Permission denied after a few calls in 2.1.116 and 2.1.117 [2 comments, 2 participants]