[BUG] `--resume` crashes with EISDIR when a previously-read file path is now a directory
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 M — e3() 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
- Start a session and read a file (e.g.,
~/project/my-script) - End the session
- Restructure the code so that path becomes a directory (e.g.,
~/project/my-script/my-script) - Try to resume:
claude --resume <session-id> - 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 callingreadFileSync()
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 wrapvB()in a broader try-catch that skips unreadable entries - Related but different from #10890 (Read tool on directory) and #14358 (/doctor EISDIR)
This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗