Edit tool returns "File has been unexpectedly modified" when file is NOT modified

Status Closed — duplicate
Maintainer reply None cached
Activity 14 comments · opened Nov 26, 2025 · closed Aug 19, 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?

Bug Description

The Edit tool repeatedly returns error "File has been unexpectedly modified. Read it again before attempting to write
it." even when no external process is modifying the file.

## Steps to Reproduce

  1. Read a file with the Read tool
  2. Immediately attempt to Edit the file
  3. Error appears despite no changes to the file

## Verification

  • Verified with certutil -hashfile <file> MD5 - hash remains identical between reads
  • No Python, VS Code, or other editor processes running
  • No cloud sync (OneDrive/Dropbox) active
  • File is on local SSD (E: drive)

## Environment

  • Windows 10/11
  • Claude Code CLI
  • Local filesystem (not network/cloud)

## Workaround
Using Python directly to modify files:
```python
with open('file.py', 'r', encoding='utf-8') as f:
content = f.read()
content = content.replace('old', 'new')
with open('file.py', 'w', encoding='utf-8') as f:
f.write(content)

Impact

  • Blocks normal workflow
  • Requires workarounds
  • Very frustrating when it persists across 10+ attempts

What Should Happen?

  1. Read a file with the Read tool
  2. Immediately attempt to Edit the file
  3. Error appears despite no changes to the file

Error Messages/Logs

Update(qt_slideshow_util2.py)
  ⎿  Error: File has been unexpectedly modified. Read it again before attempting to write it.

Steps to Reproduce

  1. Read a file with the Read tool
  2. Immediately attempt to Edit the file
  3. Error appears despite no changes to the file

Claude Model

Opus

Is this a regression?

I don't know

Last Working Version

_No response_

Claude Code Version

2.0.54 (Claude Code)

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

Ciao frm Italy to Dario and Daniela Amodei

View original on GitHub ↗

13 Comments

ryancogswell · 9 months ago

Seeing this same problem. Started 11/26/2025 and continuing 11/27. Claude Code version 2.0.55.

Platform: Windows (MINGW64_NT-10.0-20348)

Claude Opus tried several different ways to edit the file (sed, full re-write of file) that failed with the same or equivalent error. It was successful using python to do the file edits.

visma-mrange · 9 months ago

I will just add I am seeing this as well. Running Windows 11. Claude Code 2.0.55. Running in a powershell terminal. I see no edits to the file claude complains about being edited.

Exzyle-lab · 9 months ago

Environment:
Claude Code VSCode Extension
Windows 10/11
Directory: D:/Projects/RPGs/Arcanum/[SYS] Memory Bank/
Files affected: 01_State.md, 02_Log.md
Reproduction:
Read file using Read tool — succeeds
Attempt Edit tool on same file — fails with "File has been unexpectedly modified"
Re-read file — succeeds
Re-attempt Edit — fails again with same error
Loop continues indefinitely regardless of retries
Diagnostics performed:
Restarted IDE — no effect
Restarted computer — no effect
Removed read-only file attributes via PowerShell — no effect
Verified no cloud sync (disabled Google Drive sync, killed GDrive/OneDrive processes)
Ran disk check — no errors
Verified basic write access works (echo "test" > test_write.txt succeeds)
No other processes holding file locks
Key observation: Basic file I/O works fine. The issue is isolated to the Edit tool's internal cache/comparison mechanism. The tool appears to compare against a stale cached version rather than the actual file on disk. Workaround used: Bypassed Edit tool entirely using sed -i for inline text replacement. All edits completed successfully via bash, confirming this is an Edit tool-specific issue, not a system-level file access problem. Versions tested: This session occurred on 2025-11-29. Issue persisted through multiple IDE restarts and a full computer reboot.

ryancogswell · 9 months ago

Not certain this is related, but I'm mainly seeing this issue repeat when Opus is editing files within a skill. I also get prompted with every edit for skills even when I select #2 to accept all edits. Perhaps a permissions bug rather than a cache bug?

ryancogswell · 8 months ago

Uninstalling Claude Code and reinstalling it, seems to have resolved the issue for me (none of these errors in the last day).

erwinh22 · 8 months ago

Cross-referencing: A verified fix for this issue has been posted at https://github.com/anthropics/claude-code/issues/12805#issuecomment-3621343025 - patches the timestamp validation logic in cli.js to bypass the broken Windows detection.

davidrimshnick · 8 months ago

Just hit this bug again on Windows/MINGW. Workaround was using cat > file << 'EOF' via Bash instead of the Edit tool.

Hypothesis on root cause: I suspect CRLF line ending normalization is the culprit.

Git on Windows often has core.autocrlf=true, which converts LF <-> CRLF. If the Read tool normalizes content to LF internally when storing/hashing, but the Edit tool re-reads the raw file (which has CRLF on disk) before comparing, the hashes won't match - triggering a false "file has been unexpectedly modified" error.

A potential fix would be to normalize line endings before hashing, or use a content comparison that's line-ending agnostic.

Environment: Windows 10, MINGW64_NT-10.0-17763, Git Bash

kevinjbradshaw · 8 months ago

Really need to get on this. It makes claude borderline unusable!

davidrimshnick · 8 months ago

I’ll be more sympathetic to the the idea AGI is near when we don’t have
breaking bugs in the code base that’s supposed to be AGI that the AGI goes
for months without fixing

On Wed, Dec 24, 2025 at 8:28 AM kevinjbradshaw @.***>
wrote:

kevinjbradshaw left a comment (anthropics/claude-code#12462) <https://github.com/anthropics/claude-code/issues/12462#issuecomment-3689791792> Really need to get on this. It makes claude borderline unusable! — Reply to this email directly, view it on GitHub <https://github.com/anthropics/claude-code/issues/12462#issuecomment-3689791792>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/ABBNXX46X56FNGGC34Y4YAD4DKIIZAVCNFSM6AAAAACNH6H5Y6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZTMOBZG44TCNZZGI> . You are receiving this because you commented.Message ID: @.***>
LiangMu-Studio · 8 months ago

<html>
<body>
<!--StartFragment--><h2 id="root-cause-analysis-andamp-workaround" class="atx">Root Cause Analysis &amp; Workaround</h2>
<p>I analyzed the Claude Code source code and found the root cause.</p>
<h3 id="root-cause" class="atx">Root Cause</h3>
<p>Claude Code uses <strong>file system timestamps</strong> (<code>mtimeMs</code>) instead of content hashes to detect file changes. This causes false positives when cloud sync tools (Dropbox, OneDrive), IDE auto-save, or antivirus software touch file metadata without changing content.</p>
<h3 id="workaround-pretooluse-hook-with-content-hashing" class="atx">Workaround: PreToolUse Hook with Content Hashing</h3>
<p>I created a hook that uses SHA256 content hashing instead of timestamps.</p>
<p><strong>Setup:</strong></p>
<ol>
<li>Create <code>~/.claude/hooks/PathValidation.ps1</code></li>
<li>Add hook config to <code>~/.claude/settings.json</code></li>
</ol>
<details>
<summary>Click to expand: settings.json</summary>

<pre><code class="fenced-code-block language-json">{
&quot;hooks&quot;: {
&quot;PreToolUse&quot;: [
{
&quot;matcher&quot;: &quot;Read|Write|Edit|NotebookEdit&quot;,
&quot;hooks&quot;: [
{
&quot;type&quot;: &quot;command&quot;,
&quot;command&quot;: &quot;pwsh -NoProfile -ExecutionPolicy Bypass -File \&quot;%USERPROFILE%\\.claude\\hooks\\PathValidation.ps1\&quot;&quot;
}
]
}
]
}
}</code></pre>
</details>

<details>
<summary>Click to expand: PathValidation.ps1 (full script)</summary>

<pre><code class="fenced-code-block language-powershell"># PathValidation.ps1 - File sync validation hook

Uses content hash instead of timestamp to detect real changes

param()

$CacheFile = &quot;$env:USERPROFILE\.claude\hooks\.file_cache.json&quot;
$LogFile = &quot;$env:USERPROFILE\.claude\hooks\.hook.log&quot;

function Write-Log($msg) {
$timestamp = Get-Date -Format &quot;yyyy-MM-dd HH:mm:ss&quot;
&quot;$timestamp - $msg&quot; | Add-Content $LogFile -ErrorAction SilentlyContinue
}

function Get-FileHash256($path) {
if (-not (Test-Path $path -ErrorAction SilentlyContinue)) { return $null }
try {
return (Get-FileHash -Path $path -Algorithm SHA256 -ErrorAction Stop).Hash
} catch { return $null }
}

function Get-Cache {
if (Test-Path $CacheFile -ErrorAction SilentlyContinue) {
try { return Get-Content $CacheFile -Raw -ErrorAction Stop | ConvertFrom-Json -AsHashtable }
catch {}
}
return @{}
}

function Save-Cache($cache) {
try { $cache | ConvertTo-Json -Depth 10 -Compress | Set-Content $CacheFile -Force -ErrorAction Stop }
catch {}
}

$inputJson = &quot;&quot;
try { $inputJson = [Console]::In.ReadToEnd() } catch {}

Fix Windows path backslashes in JSON

$inputJson = [regex]::Replace($inputJson, &#39;(?&lt;!\\)\\(?![\\&quot;/bfnrtu])&#39;, &#39;\\&#39;)

try {
$inputObj = $inputJson | ConvertFrom-Json
$toolName = $inputObj.tool_name
$toolInput = $inputObj.tool_input

$filePath = $toolInput.file_path
if (-not $filePath) { $filePath = $toolInput.notebook_path }
if (-not $filePath) { $filePath = $toolInput.path }

if (-not $filePath) {
Write-Output &#39;{&quot;continue&quot;:true}&#39;
exit 0
}

$normalizedPath = [System.IO.Path]::GetFullPath($filePath)
$cache = Get-Cache

switch ($toolName) {
&#39;Read&#39; {
$hash = Get-FileHash256 $normalizedPath
if ($hash) {
$cache[$normalizedPath] = @{ hash = $hash }
Save-Cache $cache
Write-Log &quot;Read: $normalizedPath&quot;
}
Write-Output &#39;{&quot;continue&quot;:true}&#39;
}

{ $_ -in @(&#39;Write&#39;, &#39;Edit&#39;, &#39;NotebookEdit&#39;) } {
if (-not (Test-Path $normalizedPath -ErrorAction SilentlyContinue)) {
Write-Log &quot;New file: $normalizedPath&quot;
Write-Output &#39;{&quot;continue&quot;:true}&#39;
exit 0
}

$currentHash = Get-FileHash256 $normalizedPath
$cachedEntry = $cache[$normalizedPath]

if ($cachedEntry -and $currentHash) {
if ($cachedEntry.hash -ne $currentHash) {
Write-Log &quot;BLOCKED: $normalizedPath (content changed)&quot;
Write-Output (&#39;{&quot;continue&quot;:false,&quot;reason&quot;:&quot;File content changed externally. Please re-read: &#39; + $normalizedPath + &#39;&quot;}&#39;)
exit 0
}
}

Write-Log &quot;Allow: $normalizedPath&quot;
Write-Output &#39;{&quot;continue&quot;:true}&#39;
}

default {
Write-Output &#39;{&quot;continue&quot;:true}&#39;
}
}

} catch {
Write-Log &quot;Error: $_&quot;
Write-Output &#39;{&quot;continue&quot;:true}&#39;
}</code></pre>
</details>

<h3 id="how-it-works" class="atx">How it works</h3>

Event | Action
-- | --
Read | Cache file's SHA256 hash
Write/Edit | Compare current hash with cached
Hash matches | Allow (timestamp-only change = false positive)
Hash differs | Block and prompt to re-read

<h3 id="suggested-fix" class="atx">Suggested Fix</h3>
<p>Consider using content hashing instead of timestamps for file change detection, or as a fallback when timestamp check fails.</p>
<!--EndFragment-->
</body>
</html>

webmasterfsd · 8 months ago

I'm getting the same error, Error: File has been unexpectedly modified. Read it again before attempting to write it.

Actually, the issue started when the conversation has compacted automatically or manually. Once it is compacted, the issue has started.

19317362 · 8 months ago

Why Anthropics CAN NOT solve this BUG for SO LONG? It comes everyday for so many users . What's doing on this?

github-actions[bot] · 6 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

Showing cached comments. Read the full discussion on GitHub ↗