claude-code - 💡(How to fix) Fix [BUG] Write/Edit tools surface EBADF or ENOENT on Windows Controlled Folder Access protected paths (two error codes, one root cause) [1 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#53761Fetched 2026-04-28 06:47:57
View on GitHub
Comments
0
Participants
1
Timeline
5
Reactions
0
Participants
Timeline (top)
labeled ×4cross-referenced ×1

Claude Code's Write and Edit tools fail when the target path is inside a Windows directory protected by Controlled Folder Access (CFA) — Microsoft Defender's anti-ransomware feature. The same underlying kernel-level rejection surfaces as two distinct error codes depending on which file-system syscall is in flight:

  • Edit (modify existing) returns EBADF: bad file descriptor, write
  • Write (create new) returns ENOENT: no such file or directory, open

Both errors are misleading: the file descriptor is valid; the path exists; the kernel filter driver is blocking the syscall before the file-system layer sees it. The model receives no information about CFA being involved and burns retry budget on paths that are structurally fine but procedurally blocked.

This is one bug with two surface symptoms. Fixing only one error code leaves the other producing the same misleading-message class. Anthropic triage that catches both code paths gets a unified fix.

Error Message

Two distinct error messages from the same underlying cause:

When the Edit tool tries to modify an existing file in a CFA-protected directory:

EBADF: bad file descriptor, write

When the Write tool tries to create a new file in a CFA-protected directory:

ENOENT: no such file or directory, open

That string is the entire error payload returned to the model — no stack trace, no errno cite beyond the macro name, no path echoed, no indication that Controlled Folder Access is involved.

Defender's filter driver event log (Event Viewer → Applications and Services Logs → Microsoft → Windows → Windows Defender → Operational, Event ID 1123) records the block on the Defender side at the same time, with the harness Node binary as the rejected process and the protected path as the target. That event is not visible to the harness or the model.

Root Cause

Target: new issue at https://github.com/anthropics/claude-code/issues/new Re-rolled 2026-04-27 to fold in Archivist's CFA probe-matrix + Manager's 4th-operator data point + Tyr's 5th-operator data point + sharpened "two error codes, one root cause" framing.

Fix Action

Fix / Workaround

  • Each EBADF/ENOENT failure costs ~30 seconds of model tokens spent on retries against the same procedurally-blocked path, plus user-visible noise ("why is the agent retrying").
  • The workaround is not discoverable from the error message alone; it requires the user (or the agent) to know about CFA and the executable-allowlist concept independently. Whichever agent first hits this on a given host has to discover the workaround the hard way; subsequent agents on the same host re-discover it independently.
  • Workaround discipline became durable runbook material across multiple agents over a week of independent encounters. Tribal knowledge tax across an agent ecosystem.
  • Allowlist-via-Defender-UI requires admin privilege (UAC). Allowlist contents are also admin-gated for enumeration — agents cannot probe in advance whether the harness binary is allowlisted; the only signal is the failure itself.

Workarounds that succeed

Both workarounds are reliable across multiple operators on the same configuration. Neither is discoverable from the harness's error messages alone.

Code Example

Write/Edit tools surface EBADF or ENOENT on Windows Controlled Folder Access protected paths (two error codes, one root cause)

---

EBADF: bad file descriptor, write

---

ENOENT: no such file or directory, open

---

Two distinct error messages from the same underlying cause:

When the Edit tool tries to modify an existing file in a CFA-protected directory:

    EBADF: bad file descriptor, write

When the Write tool tries to create a new file in a CFA-protected directory:

    ENOENT: no such file or directory, open

That string is the entire error payload returned to the model — no stack trace, no errno cite beyond the macro name, no path echoed, no indication that Controlled Folder Access is involved.

Defender's filter driver event log (Event ViewerApplications and Services LogsMicrosoftWindowsWindows DefenderOperational, Event ID 1123) records the block on the Defender side at the same time, with the harness Node binary as the rejected process and the protected path as the target. That event is not visible to the harness or the model.
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?

Class B — Owner submission packet (v2 — sharpened with multi-agent corpus)

Target: new issue at https://github.com/anthropics/claude-code/issues/new Re-rolled 2026-04-27 to fold in Archivist's CFA probe-matrix + Manager's 4th-operator data point + Tyr's 5th-operator data point + sharpened "two error codes, one root cause" framing.

Suggested title

Write/Edit tools surface EBADF or ENOENT on Windows Controlled Folder Access protected paths (two error codes, one root cause)

Suggested labels (if permitted)

bug, windows, error-handling, area:tools

Duplicate-check (done 2026-04-27 — clear to submit)

Searched anthropics/claude-code issues across 4 angles: EBADF, Controlled Folder Access, MpFilter, bad file descriptor. No matches on this class. Existing EBADF issues are on Cowork rootfs.vhdx rename / Claude Desktop git-worktrees.json renameSync / Git Bash stdout pipe — different code paths, different syscalls.

Pre-submission verification (Owner checklist before paste)

#ItemVerified
1No username (repom) anywhere in issue body— verify
2No internal project / agent / workspace names in issue body— verify
3No internal rule numbers / session numbers in issue body— verify
4All paths generic / placeholder— verify
5Issue body length reasonable (~200-280 rendered lines)— verify
6First-paragraph summary accurate + actionable— verify
7No single quotes around placeholder paths that would break GitHub markdown— verify

After all 7 verified clean, copy everything between the two --- markers below into the issue body field at github.com/anthropics/claude-code/issues/new.


Summary

Claude Code's Write and Edit tools fail when the target path is inside a Windows directory protected by Controlled Folder Access (CFA) — Microsoft Defender's anti-ransomware feature. The same underlying kernel-level rejection surfaces as two distinct error codes depending on which file-system syscall is in flight:

  • Edit (modify existing) returns EBADF: bad file descriptor, write
  • Write (create new) returns ENOENT: no such file or directory, open

Both errors are misleading: the file descriptor is valid; the path exists; the kernel filter driver is blocking the syscall before the file-system layer sees it. The model receives no information about CFA being involved and burns retry budget on paths that are structurally fine but procedurally blocked.

This is one bug with two surface symptoms. Fixing only one error code leaves the other producing the same misleading-message class. Anthropic triage that catches both code paths gets a unified fix.

Environment

  • OS: Windows 11 Home 10.0.26200
  • Harness: Claude Code, VSCode native extension build, version 2.1.120 (latest at time of filing; reproducible across multiple sessions on prior versions)
  • Models: reproduced on Opus 4.7 (1M context) and additional Claude models
  • Shell: Git Bash (MSYS2) on Windows; PowerShell 7.x available
  • Defender: Controlled Folder Access enabled with multiple user directories added to protected paths
  • Allowlist state: bash.exe and pwsh.exe are on the CFA executable allowlist; the Claude Code harness binary (bundled Node.js) is NOT

Verbatim errors returned to the model

For Edit on existing protected file:

EBADF: bad file descriptor, write

For Write (create new) on protected directory:

ENOENT: no such file or directory, open

In both cases that string is the entire error payload returned to the model — no stack trace, no errno cite beyond the macro name, no path echoed, no indication that CFA is involved.

Steps to reproduce

  1. On Windows 11, enable Microsoft Defender Controlled Folder Access (Windows Security → Virus & threat protection → Ransomware protection → Manage Controlled folder access → On).
  2. Add a directory to the protected list (e.g. C:\protected-test\).
  3. Verify allowlist state: bash.exe and pwsh.exe on the CFA executable allowlist (typical default after first invocation); the Claude Code harness binary NOT on the allowlist.
  4. Open a Claude Code session at any cwd.
  5. Place an existing file at C:\protected-test\sample.ps1 (any reasonable text content).

Reproducer A — Edit returns EBADF:

Ask the model to use the Edit tool to modify C:\protected-test\sample.ps1 (any non-trivial change).

StepResult
Read the protected fileSUCCEEDS
Edit with multi-line old_string/new_stringFAILS with EBADF: bad file descriptor, write
Edit retry, identical paramsFAILS EBADF (same)
Read again to refresh harness FDSUCCEEDS
Edit again with same paramsFAILS EBADF (same)
Edit with a trivial diff (single space added)FAILS EBADF (rules out content size)
Same Edit tool on a non-CFA path in the same sessionSUCCEEDS

Reproducer B — Write returns ENOENT:

Ask the model to use the Write tool to create a new file at C:\protected-test\new-file.tmp.

StepResult
ls C:\protected-test\ via BashSUCCEEDS (directory exists, listable)
Write new file inside the protected directoryFAILS with ENOENT: no such file or directory, open
Write retry, identical paramsFAILS ENOENT
Same Write tool on a non-CFA pathSUCCEEDS

Probe matrix (the load-bearing diagnostic)

The probe matrix isolates the blocked actor by running the same write attempt through different processes:

#MechanismPath classResult
1Edit tool, harnessCFA-protected, existing file (modify)FAIL EBADF: bad file descriptor, write
2Edit tool, harnessNON-CFA pathSUCCESS (boundary control)
3Write tool, harnessCFA-protected, new file (create)FAIL ENOENT: no such file or directory, open
4Bash shell redirection (e.g. echo > path) via bash.exeCFA-protected, new fileSUCCESS
5Bashpowershell.exe -Command "Set-Content -Path <path>"CFA-protected, new fileSUCCESS
6Bashpython read+replace+write loop via python.exe (typical Windows install)CFA-protected, existing fileSUCCESS

Bash and PowerShell both succeed because both are on the CFA executable allowlist (typical default after first invocation, or admin-added). Python typically also lands on the allowlist if the user runs it from any CFA-protected path before. The Claude Code harness's bundled Node.js process is the single common element across the failures — it is not on the allowlist, so its WriteFile syscalls into protected paths are filter-driver-rejected.

Single common element identified, single fix surface.

Cross-operator reproducibility

Reproduced independently across multiple operators on the same Windows 11 host within a single week of investigation. Path-in-additional-working-dirs status does NOT predict outcome:

OperatorToolSymptomPath-in-additional-working-dirs
AWrite (~10 calls, control)success on non-CFA pathsYES
AWrite + Edit, multiple, on CFA-protected pathsENOENT + EBADFYES (own deep workspace, but CFA-protected)
BWriteENOENTNO (sibling-of-cwd, CFA-protected)
CEditEBADFNO (sibling-of-cwd, CFA-protected) — same path class as B with Edit instead of Write
DWrite (5+ times)ENOENTYES (own deep workspace, CFA-protected)

Path-in-additional-working-dirs being YES does not prevent the failure. CFA-protected status is the predictor; AWD scope is not.

Boundary evidence (rules out other causes)

  • The same harness, same session, same model, same Edit/Write tool succeeds on a non-CFA path immediately before and after the failing call. Confirms it is not a generic tool fault, not per-session FD exhaustion, not a model/prompt issue.
  • File ACLs are normal -rw-r--r--; Read works on the protected file fine. Confirms it is not a Windows ACL permission issue.
  • The boundary is precisely the CFA scope. Files inside protected directories fail; files outside succeed.
  • The failure does NOT depend on the harness's additionalDirectories configuration (operators with AWD covering the path AND operators with AWD not covering the path both reproduce the failure).

Why CFA surfaces as EBADF (Edit) vs ENOENT (Write)

Controlled Folder Access enforcement runs in the Microsoft Defender kernel filter driver (MpFilter.sys). When a non-allowlisted process invokes a file-system syscall that targets a path inside a protected directory, the driver fails the syscall before the file-system layer sees it. Node.js (which the Claude Code harness uses) maps the underlying NTSTATUS rejection to libuv error codes — and libuv distinguishes between syscall paths:

  • Edit performs open(...) (succeeds, FD valid) followed by write(fd, ...). The write is the syscall the filter driver rejects. libuv surfaces this as UV_EBADF, which lands in the JavaScript layer as EBADF: bad file descriptor, write. The FD itself is valid; the write is what's blocked.
  • Write (creating a new file) performs open(..., O_CREAT). The filter driver rejects the create attempt before the file ever exists. libuv surfaces this as UV_ENOENT, which lands as ENOENT: no such file or directory, open. The path's parent directory exists and is listable, but the create-on-write is rejected at the kernel layer.

Same root rejection, two different libuv error mappings depending on whether the syscall is open-on-FD vs write-on-FD. Anyone fixing this on Anthropic's side will see two surface bugs from one underlying cause — catching both error codes in the tool layer is the unified fix.

Operational impact

  • Each EBADF/ENOENT failure costs ~30 seconds of model tokens spent on retries against the same procedurally-blocked path, plus user-visible noise ("why is the agent retrying").
  • The workaround is not discoverable from the error message alone; it requires the user (or the agent) to know about CFA and the executable-allowlist concept independently. Whichever agent first hits this on a given host has to discover the workaround the hard way; subsequent agents on the same host re-discover it independently.
  • Workaround discipline became durable runbook material across multiple agents over a week of independent encounters. Tribal knowledge tax across an agent ecosystem.
  • Allowlist-via-Defender-UI requires admin privilege (UAC). Allowlist contents are also admin-gated for enumeration — agents cannot probe in advance whether the harness binary is allowlisted; the only signal is the failure itself.

Workarounds that succeed

For text-class edits on existing files:

  1. Bash heredoc: write a small PowerShell or Python script outside the CFA scope (e.g. into %TEMP%).
  2. Bash invokes powershell.exe -NoProfile -ExecutionPolicy Bypass -File <script> (or python <script>).
  3. The external script reads the protected file, performs the edit in-memory, writes back. Because the executable is on the CFA allowlist, the kernel filter driver permits the write.
  4. Read the file post-write — shows the expected diff.

For new files in protected directories:

  1. Write the file to %TEMP% (non-CFA-protected by default).
  2. Bash cp from %TEMP% into the protected directory. Bash is on the CFA allowlist; the copy succeeds.
  3. Optionally rm the %TEMP% source file via Bash for cleanup.

Both workarounds are reliable across multiple operators on the same configuration. Neither is discoverable from the harness's error messages alone.

Suggested fixes

Three options, ordered by user-friendliness:

  1. Catch CFA-class failures at the tool level and surface a clearer error to the model, distinguishing both code paths under one diagnostic message:

    Write blocked by Windows Controlled Folder Access. The Claude Code harness executable is not on the CFA allowlist for path "<path>". This affects both new-file creation (returns ENOENT) and existing-file modification (returns EBADF). Suggested: ask user to add the harness to CFA allowlist via Windows Security → Virus & threat protection → Manage ransomware protection → Allow an app through Controlled folder access; OR work outside protected paths; OR use Bash to invoke an allowlisted executable (powershell.exe, bash.exe, python.exe) to perform the write.

    The current EBADF and ENOENT error strings are wrong on their face for this failure mode and give the model nothing to act on.

  2. Document this in the Write and Edit tool descriptions so models can preemptively route through a CFA-allowlisted executable when working in protected paths. A single sentence in each tool's description would close the discoverability gap and avoid wasted retry cycles. Cite both error codes (EBADF, ENOENT) so models recognize either as the same class.

  3. Detect protected directories at session start or tool-call time by probing a write to a tempfile within the cwd's parent tree; classify directories as CFA-protected if EBADF/ENOENT returns; warn the model in the system context. This is heavier implementation but eliminates the wrong-path retry waste entirely. Could also surface a one-time toast/notification suggesting the user add the harness to the CFA allowlist.

A complementary option (out of scope for the tool layer but worth surfacing): add the Claude Code harness binary to a default CFA allowlist on installation. This is an installer-time decision that would eliminate the failure mode for new users without requiring them to learn about CFA. Existing installations would still benefit from options 1-3.

Additional context

  • This is not a security-critical bug — CFA is doing exactly what it should (blocking writes from non-allowlisted processes to protected paths). The issue is the harness's surfacing of the failure to the model.
  • Multiple operators independently hit this on the same machine within a week of each other (separate sessions, separate cwds, same machine, same Defender CFA configuration). Cross-agent reproducibility is high.
  • Workaround via Bash + allowlisted shell is well-known internally now and saved as durable runbook material; it is tribal knowledge each new agent must independently discover.
  • The probe matrix (Bash + PowerShell allowlisted, harness Node not) is empirically reproducible by any operator — a useful diagnostic for triage to confirm the mechanism on a Windows host with CFA enabled.

Thank you for Claude Code — the tooling has been valuable for our workflow; this specific error-class is the only surface where the harness's error reporting actively misleads the model.


After submission

Once the issue is filed, please share the issue number / URL back. I'll capture proof-of-submission to OB (paired with the Class A #53734 loop-close) and then route the Class C extract (which is a comment on existing issue #50289, with a placeholder for this Class B issue number that I'll fill in on submission).

What Should Happen?

When the Write or Edit tool fails because Windows Controlled Folder Access is blocking it, the harness should return a clear error message saying so — something like "Write blocked by Windows Controlled Folder Access; the Claude Code harness is not on the CFA allowlist for this path." The current EBADF and ENOENT errors are misleading because they make it look like there's something wrong with the file or its descriptor, when really Defender is blocking the write at the kernel level. A clear error would let the model either ask the user to add Claude Code to the CFA allowlist, work outside protected paths, or use Bash to invoke an already-allowlisted process (powershell.exe, bash.exe) to perform the write.

Both error codes (EBADF on Edit, ENOENT on Write) should surface the same diagnostic — they're two faces of the same underlying CFA rejection.

Error Messages/Logs

Two distinct error messages from the same underlying cause:

When the Edit tool tries to modify an existing file in a CFA-protected directory:

    EBADF: bad file descriptor, write

When the Write tool tries to create a new file in a CFA-protected directory:

    ENOENT: no such file or directory, open

That string is the entire error payload returned to the model — no stack trace, no errno cite beyond the macro name, no path echoed, no indication that Controlled Folder Access is involved.

Defender's filter driver event log (Event Viewer → Applications and Services Logs → Microsoft → Windows → Windows Defender → Operational, Event ID 1123) records the block on the Defender side at the same time, with the harness Node binary as the rejected process and the protected path as the target. That event is not visible to the harness or the model.

Steps to Reproduce

  1. On Windows 11, enable Microsoft Defender Controlled Folder Access: Windows Security → Virus & threat protection → Ransomware protection → Manage Controlled folder access → toggle ON

  2. Add a directory to the protected list (e.g. C:\protected-test).

  3. Confirm allowlist state: bash.exe and pwsh.exe are typically on the CFA executable allowlist after first invocation; the Claude Code harness binary (bundled Node.js) is NOT on the allowlist by default.

  4. Open a Claude Code session at any working directory.

  5. Place an existing file at C:\protected-test\sample.txt with any content.

REPRODUCER A — Edit returns EBADF:

  • Ask the model to use the Edit tool to modify C:\protected-test\sample.txt (any non-trivial change).
  • Edit fails with: EBADF: bad file descriptor, write
  • Read on the same file SUCCEEDS.
  • Edit on a non-CFA-protected path in the same session SUCCEEDS.

REPRODUCER B — Write returns ENOENT:

  • Ask the model to use the Write tool to create a new file at C:\protected-test\new-file.txt.
  • Write fails with: ENOENT: no such file or directory, open
  • ls C:\protected-test\ via Bash SUCCEEDS (directory exists, listable).
  • Write on a non-CFA-protected path in the same session SUCCEEDS.

PROBE MATRIX (the diagnostic that isolates the cause): Run the same write attempt through different processes:

  • Edit/Write tool (harness Node binary): FAIL
  • Bash shell redirection via bash.exe: SUCCESS
  • powershell.exe -Command "Set-Content -Path ...": SUCCESS
  • python.exe read+replace+write loop: SUCCESS

Bash, PowerShell, and Python succeed because they are on the CFA allowlist. The Claude Code harness's bundled Node.js process is the single common element across the failures — it is not on the allowlist, so its WriteFile syscalls into protected paths are filter-driver-rejected.

Single common element identified, single fix surface.

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

No response

Claude Code Version

Claude Code 2.1.120 (VSCode native extension build) on Windows 11 Home 10.0.26200

Platform

Other

Operating System

Windows

Terminal/Shell

VS Code integrated terminal

Additional Information

WHY THE TWO ERROR CODES SHOW UP FOR THE SAME ROOT CAUSE

Defender's CFA enforcement runs in the kernel filter driver (MpFilter.sys). When a non-allowlisted process tries to write to a protected path, the driver fails the syscall before the filesystem layer ever sees it. Node.js (which the Claude Code harness uses) maps the underlying NTSTATUS rejection to libuv error codes — and libuv distinguishes between syscall paths:

  • Edit performs open() (succeeds, FD valid) followed by write(fd, ...). The WRITE is what the filter driver rejects. libuv surfaces this as UV_EBADF, which lands in JavaScript as "EBADF: bad file descriptor, write". The FD is actually valid; the write is what's blocked.

  • Write (creating a new file) performs open(..., O_CREAT). The filter driver rejects the create attempt before the file ever exists. libuv surfaces this as UV_ENOENT, which lands as "ENOENT: no such file or directory, open". The parent directory exists and is listable, but the create is rejected at the kernel layer.

Same root rejection, two different libuv error mappings depending on whether the syscall is open-on-FD vs write-on-FD. Catching both error codes in the tool layer is the unified fix.

CROSS-OPERATOR REPRODUCIBILITY

Reproduced independently across multiple operators on the same Windows 11 host within a single week of investigation. Path-in-additional-working-dirs status does NOT predict outcome — operators with the path inside their AWD AND operators with the path outside their AWD both reproduce the failure. CFA- protected status is the predictor; AWD scope is not.

WORKAROUNDS THAT SUCCEED

For text-class edits on existing files:

  1. Bash heredoc: write a small PowerShell or Python script outside the CFA scope (e.g. into %TEMP%).
  2. Bash invokes powershell.exe or python.exe to read the protected file, perform the edit in-memory, and write back. Because the executable is on the CFA allowlist, the kernel filter driver permits the write.

For new files in protected directories:

  1. Write the file to %TEMP% (non-CFA-protected by default).
  2. Bash cp from %TEMP% into the protected directory.

Both workarounds are reliable but not discoverable from the harness's error messages alone — every new agent that hits this re-discovers the workaround the hard way.

SUGGESTED FIXES (ordered by user-friendliness)

  1. Catch CFA-class failures at the tool level and surface a clearer error, distinguishing both EBADF and ENOENT under one diagnostic message:

    "Write blocked by Windows Controlled Folder Access. The Claude Code harness executable is not on the CFA allowlist for path <path>. This affects both new-file creation (returns ENOENT) and existing-file modification (returns EBADF). Suggested: ask user to add the harness to the CFA allowlist, OR work outside protected paths, OR use Bash to invoke an allowlisted executable (powershell.exe, bash.exe, python.exe) to perform the write."

  2. Document this in the Write and Edit tool descriptions so models can preemptively route through a CFA-allowlisted executable when working in protected paths. A single sentence in each tool's description would close the discoverability gap.

  3. (Heavier) Detect protected directories at session start by probing a write to a tempfile in the cwd's parent tree; classify directories as CFA-protected if EBADF/ENOENT returns; warn the model in the system context. Eliminates wrong-path retry waste entirely.

A complementary option: add the Claude Code harness binary to a default CFA allowlist on installation. This is an installer-time decision that would eliminate the failure mode for new users without requiring them to learn about CFA. Existing installations would still benefit from options 1-3.

OPERATIONAL IMPACT

Each EBADF/ENOENT failure costs ~30 seconds of model tokens spent on retries against the same procedurally-blocked path, plus user-visible noise. The workaround is not discoverable from the error message alone; it requires knowing about CFA and the executable-allowlist concept independently. Allowlist-via-Defender-UI requires admin privilege (UAC), and allowlist contents are also admin-gated for enumeration — agents cannot probe in advance whether the harness binary is allowlisted; the only signal is the failure itself.

This is not a security-critical bug — CFA is doing exactly what it should (blocking writes from non-allowlisted processes to protected paths). The issue is the harness's surfacing of the failure to the model.

Thank you for Claude Code — the tooling has been valuable for our workflow; this specific error-class is the only surface where the harness's error reporting actively misleads the model.

extent analysis

TL;DR

The issue can be fixed by catching CFA-class failures at the tool level and surfacing a clearer error message, distinguishing both EBADF and ENOENT under one diagnostic message, or by documenting this in the Write and Edit tool descriptions.

Guidance

  • Identify if the error is due to Windows Controlled Folder Access (CFA) by checking the error messages EBADF: bad file descriptor, write or ENOENT: no such file or directory, open.
  • Verify if the Claude Code harness binary is on the CFA allowlist.
  • Consider adding the harness binary to the CFA allowlist or using a workaround such as writing to a non-protected path and then moving the file to the protected directory using a CFA-allowlisted process like Bash.
  • Update the tool descriptions to include information about CFA and the potential for these errors.

Example

To catch CFA-class failures, the tool could check for the specific error codes and return a custom error message, such as:

if (error.code === 'EBADF' || error.code === 'ENOENT') {
  return 'Write blocked by Windows Controlled Folder Access. The Claude Code harness executable is not on the CFA allowlist for path <path>.';
}

Notes

The provided solution assumes that the issue is indeed caused by Windows Controlled Folder Access and that the harness binary is not on the CFA allowlist. Additional debugging may be necessary to confirm the root cause.

Recommendation

Apply a workaround, such as adding the harness binary to the CFA allowlist or using a CFA-allowlisted process to perform the write, as this is a more straightforward solution that does not require modifying the tool's error handling.

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