[BUG] `Read` tool returns "file unchanged" after external on-disk edits, serving a stale cached snapshot
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?
The Read tool suppresses re-reads with the message:
Wasted call — file unchanged since your last Read. Refer to that earlier tool_result instead.
This freshness check appears to track only edits made by the assistant's own tools (Edit, Write, NotebookEdit), not modifications to the file on disk from other sources (IDE save, another terminal, another process). When a file is edited externally between two Read calls, the second Read falsely reports the file as unchanged and refuses to return current content, causing the assistant to operate on a stale view.
This is inconsistent with the Edit tool, which the tools reference documents as performing a real disk-state check:
Read-before-edit: Claude must have read the file in the current conversation, and the file must not have changed on disk since that read.
The Read tool section does not document any "unchanged" suppression behavior at all, so the message is also undocumented.
Environment
- Claude Code VSCode native extension, version 2.1.144
- macOS (Darwin 25.5.0)
- Model:
claude-opus-4-7(Opus 4.7, 1M context)
Where this was observed
Reproduced inside the Claude Code VSCode native extension (v2.1.144). The Read tool itself is a built-in Claude Code tool shared across surfaces (CLI, IDE extensions), so I'd expect the same staleness suppression to fire in the CLI whenever a file is modified by an external writer (another terminal, a git pull, a formatter, a second agent) between two Read calls — but I haven't verified that. Worth confirming during triage.
Actual
Read returns the "unchanged" message based on the assistant's own edit history only, ignoring external writes.
Notes / things worth checking
- Whether the suppression keys on path only, or path + something stat-based that's missing the invalidation.
- Whether VSCode's notebook save (atomic write-and-rename) interacts oddly with mtime-based checks.
- Whether
NotebookEditproperly updates whatever staleness-tracking stateReadconsults (in my case the external edits happened afterNotebookEdit, so this is a separate variable, but worth isolating). - A minimal repro should be possible with a plain
.txtfile edited viaecho > filefrom another terminal between twoReadcalls.
Workaround
Use Bash (cat, jq, etc.) to re-read a file when it may have been edited outside the current Claude session.
What Should Happen?
Read should stat the file (mtime, size, or content hash) and return fresh content whenever the on-disk state differs from the cached snapshot — matching Edit's read-before-edit invariant.
Error Messages/Logs
`Wasted call — file unchanged since your last Read. Refer to that earlier tool_result instead.`
Steps to Reproduce
- Assistant
Reads a Jupyter notebook (returns content). - Assistant makes several
NotebookEditcalls against specificcell_ids in that file. - User edits the same notebook in the VSCode notebook editor (reorders cells, deletes a cell, changes cell text). File is saved to disk.
- Assistant calls
Readon the same path → returns the "Wasted call — file unchanged" string instead of fresh content. - Assistant runs
cat … | jqviaBashon the same path → returns the actually current on-disk content, confirming the file had changed andReadwas wrong.
Claude Model
Opus
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
Claude Code VSCode native extension, version 2.1.144
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
VS Code integrated terminal
Additional Information
_No response_
This issue has 7 comments on GitHub. Read the full discussion on GitHub ↗