[BUG] Windows: every file on an exFAT volume is flagged as a sensitive file (readlink returns EISDIR, not EINVAL)

Status Open
Reported on v2.1.284
Maintainer reply None cached
Activity 1 comment · opened Oct 1, 2026

Summary

On Windows, when the project lives on an exFAT volume, every file in it is treated as a "sensitive file":

  • Accept edits mode: every Edit/Write prompts with "Claude requested permissions to edit <path> which is a sensitive file." "Always allow" is never offered.
  • Auto mode: every Edit/Write fails with "classifier gave no verdict (it skipped this action)".
  • Edit(**) / Write(**) allow rules in .claude/settings.local.json make no difference.
  • Files on an NTFS volume (for example the session scratchpad on C:) are unaffected in the same session.

Environment

  • Claude Code 2.1.284, launched by the Claude desktop app 2.16120.0.0 (Code tab)
  • Windows 11 Pro 10.0.26200
  • Project on G:, an external USB SSD formatted exFAT (reported by Windows as a Fixed drive)
  • Started on 2026-09-30, the first restart after the desktop app updated on 2026-09-29

Steps to reproduce

  1. Put any git repository on an exFAT volume.
  2. Open it in the desktop app's Code tab (the app loads its built-in anthropic-skills plugin into the session).
  3. In Accept edits mode, ask Claude to edit any ordinary source file.

Expected: the edit is applied without a prompt.
Actual: a "sensitive file" prompt for every edit, with no "Always allow".

Likely cause

The sensitive-file check walks each directory component of the target path and calls readlink on it to tell a plain directory from a junction. The result is classified as: EINVAL = plain directory, ENOENT = absent, anything else = error, and an error makes the whole path untrusted.

On NTFS, readlink on a plain directory fails with EINVAL. On exFAT, which has no reparse points, it fails with EISDIR instead, so every directory on the volume is classified as an error and every file under it becomes "sensitive".

Reproduction of the error-code difference (Node 26.4.0 on the same machine; I could not run the bundled runtime directly):

const fs = require('fs');
for (const p of ['C:/Users', 'G:/Projects']) {   // NTFS, exFAT
  try { fs.readlinkSync(p); } catch (e) { console.log(p, e.code); }
}
// C:/Users    EINVAL
// G:/Projects EISDIR

The walk appears to run only when the session has inline plugins, which is always the case in the desktop app. The same classification logic is present in 2.1.281, so this does not look like a 2.1.284 regression in that function; the desktop app update is the more likely trigger.

FAT32 volumes probably behave the same way (not tested).

Suggested fix

When lstat reports a directory that is not a symbolic link and readlink fails with EISDIR (the filesystem does not support reparse points), treat it as a plain directory rather than an error.

Workaround

Move the project to an NTFS volume.

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗