[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_
8 Comments
Found 1 possible duplicate issue:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
claude-code #60684: Read Tool Returns Stale Cached Snapshot After External Edits
Issue: https://github.com/anthropics/claude-code/issues/60684
Type: Bug — Data Staleness (area:tools, has repro, platform:macos, platform:vscode)
Severity: HIGH — causes assistant to operate on stale data
Quote: $2,000–$3,000
Root Cause Analysis
The Read tool implements a "file unchanged" suppression that tracks only the assistant's own tool operations (Edit, Write, NotebookEdit) but does NOT track external file modifications. This creates a staleness gap when files are modified by external sources between two Read calls.
Technical Analysis
The current freshness check mechanism:
Inferred Implementation
Why Edit Tool Works Correctly
The Edit tool performs a real disk-state check because it needs to verify the file hasn't changed since the last read (to prevent edit conflicts). This check uses file system metadata (mtime, inode) rather than just tracking tool operations.
Proposed Fix
Fix 1: Real Disk-State Check in Read Tool
Fix 2: Invalidate Cache on External Watch Events
For VSCode/IDE integration, listen to file change events:
Fix 3: Add Staleness Indicator
When returning suppressed results, include staleness info:
Testing Plan
Risk Assessment
Estimated Effort
---
Solution submitted for review. Estimated effort and quote available upon request.
Apparently Jupyter notebooks have a specialized harness to manipulate cells within it. #45748 is a similar issue related to reading a text file after a git operation; however, this bug affects the read operations of specific cells using the Jupyter notebook harness. Perhaps there is common code that affects read operations in both cases but that would need to be confirmed.
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
This is still happening in v2.1.185 today. It is a GENERAL bug that needs to be fixed. It should not have a status of NOT PLANNED.
If I tell the LLM that I modified the file the following happens:
Here is the output from Claude CLI:
I modified tasks.txt. Add another task at the end for the following: Verify that Content\Scripts\Examples\12-zoom-spiral-feedback.js is producing the output as expected. It only draws a filled circle in the middle of the screen and nothing else. Please fix.
● Read(F:\Programming\CSharp\MusicTo3D\docs\tasks.txt)
Unchanged since last read
● Read(F:\Programming\CSharp\MusicTo3D\docs\tasks.txt · lines 40-79)
Read 0 lines
● Read(F:\Programming\CSharp\MusicTo3D\docs\tasks.txt)
Read 33 lines
This should be a simple fix. We even have a code proposal. All these AI tools and its too much work for Claude to fix itself?
@rstander7777 I observed this in the notebook (ipynb) file extension. I don't see this with regular text files.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.