[BUG] `--resume` crashes with EISDIR when a previously-read file path is now a directory

Resolved 💬 1 comment Opened Mar 31, 2026 by itsutose Closed Apr 10, 2026

Preflight Checklist

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

What's Wrong?

claude --resume <session-id> crashes with EISDIR: illegal operation on a directory, read when a file that was read during the session has since been replaced by a directory at the same path.

During resume, Claude Code rebuilds the file cache by re-reading all file paths that were accessed via the Read tool during the session. The function vB() calls readFileSync() on each recorded path. If any of those paths is now a directory (e.g., a file was moved into a subdirectory with the same name), readFileSync() throws EISDIR and the resume crashes because the error is not caught.

Root Cause

In cli.js, the file cache rebuild logic (around line 1681) iterates over tool_use results and calls vB()readFileSync() on recorded file paths. The only error check is if(!e3(M))throw Me3() does not handle EISDIR, so it propagates and crashes the process.

// Approximate deobfuscated logic:
let J = A.get(w.tool_use_id);  // A maps tool_use_id → file path
if (J && w.is_error !== true) try {
    let { content: M } = vB(J);  // vB calls readFileSync
    z.set(J, { content: M, timestamp: ik(J), ... });
} catch (M) {
    if (!e3(M)) throw M;  // EISDIR not handled → crash
}

Steps to Reproduce

  1. Start a session and read a file (e.g., ~/project/my-script)
  2. End the session
  3. Restructure the code so that path becomes a directory (e.g., ~/project/my-script/my-script)
  4. Try to resume: claude --resume <session-id>
  5. Crash with EISDIR

Concrete example

# During session: Read tool accessed /path/to/claude-resume (a file)
# After session: file was moved to /path/to/claude-resume/claude-resume (directory created)
# Resume → readFileSync("/path/to/claude-resume") → EISDIR

What Should Happen?

The file cache rebuild should gracefully handle paths that are no longer readable files:

  • Catch EISDIR (and other filesystem errors) in the vB() call and skip the entry
  • Or check with statSync().isFile() before calling readFileSync()

Error Message

ERROR  EISDIR: illegal operation on a directory, read

 node:fs:736:18

 - Module.readSync (node:fs:736:18)
 - Object.readSync (...cli.js:48:1403)
 - am6 (...cli.js:129:12379)
 - vB (...cli.js:130:178)
 - hV6 (...cli.js:1681:355)

Environment

  • Claude Code: 2.1.88
  • Node.js: v22.22.2
  • OS: macOS (Darwin 25.3.0 arm64)
  • Installation: volta

Notes

  • Sessions where no Read-accessed file paths changed to directories resume fine
  • The fix would be trivial: add EISDIR to the error types handled by e3(), or wrap vB() in a broader try-catch that skips unreadable entries
  • Related but different from #10890 (Read tool on directory) and #14358 (/doctor EISDIR)

View original on GitHub ↗

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