You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Edit/Write tools fail with 'File has been unexpectedly modified' on Windows (MINGW) #12805
Updated Patch for Claude Code (Windows "File has been unexpectedly modified" fix)
The obfuscated variable names change between versions. Here are the patterns:
Version
validateInput
validateInput2
Write/Edit tool throw
v2.0.75
Ew(B)>J.timestamp
Ew(Y)>W.timestamp
\!z||E>z.timestamp
v2.0.72
Vw(B)>J.timestamp
Vw(Y)>W.timestamp
\!R||M>R.timestamp
v2.0.64
KE(B)>I.timestamp
KE(Y)>W.timestamp
\!C||F>C.timestamp
v2.0.62
oD(B)>J.timestamp
oD(Y)>W.timestamp
\!C||E>C.timestamp
Bash/Git Bash Patch Commands (v2.0.75)
CLAUDE_CLI="/c/Users/$USER/AppData/Roaming/npm/node_modules/@anthropic-ai/claude-code/cli.js"# Backup first
cp "$CLAUDE_CLI""${CLAUDE_CLI}.backup"# Patch 1: validateInput timestamp check
sed -i 's/if(Ew(B)>J.timestamp)return{result:\!1,message:"File has been modified since read/if(false)return{result:\!1,message:"File has been modified since read/'"$CLAUDE_CLI"# Patch 2: validateInput timestamp check (behavior:ask variant)
sed -i 's/if(Ew(Y)>W.timestamp)return{result:\!1,behavior:"ask",message:"File has been modified since read/if(false)return{result:\!1,behavior:"ask",message:"File has been modified since read/'"$CLAUDE_CLI"# Patch 3: Write tool throw check
sed -i 's/if(\!z||E>z.timestamp)throw Error("File has been unexpectedly modified/if(false)throw Error("File has been unexpectedly modified/'"$CLAUDE_CLI"echo"Patch applied\! Restart Claude Code."
PowerShell Patch Commands (v2.0.75)
$cliPath="$env:APPDATA\npm\node_modules\@anthropic-ai\claude-code\cli.js"Copy-Item$cliPath"$cliPath.backup"$content=Get-Content$cliPath-Raw
# Patch all 3 patterns for v2.0.75$content=$content-replace'if\(Ew\(B\)>J\.timestamp\)return\{result:\!1,message:"File has been modified since read','if(false)return{result:\!1,message:"File has been modified since read'$content=$content-replace'if\(Ew\(Y\)>W\.timestamp\)return\{result:\!1,behavior:"ask",message:"File has been modified since read','if(false)return{result:\!1,behavior:"ask",message:"File has been modified since read'$content=$content-replace'if\(\!z\|\|E>z\.timestamp\)throw Error\("File has been unexpectedly modified','if(false)throw Error("File has been unexpectedly modified'Set-Content$cliPath$content-NoNewline
Write-Host"Patched\! Restart Claude Code."
Auto-Patch Script (SessionStart Hook)
For automatic patching on startup, save as ~/.claude/hooks/auto_patch_windows_edit.py:
#\!/usr/bin/env python3importre, shutilfrompathlibimportPathdefpatch():
cli=Path("C:/Users/YOUR_USER/AppData/Roaming/npm/node_modules/@anthropic-ai/claude-code/cli.js")
ifnotcli.exists(): returncontent=cli.read_text(encoding="utf-8")
patterns= [
# v2.0.75
(r'if\(Ew\(B\)>J\.timestamp\)return\{result:\!1,message:"File has been modified since read', 'if(false)return{result:\!1,message:"File has been modified since read'),
(r'if\(Ew\(Y\)>W\.timestamp\)return\{result:\!1,behavior:"ask",message:"File has been modified since read', 'if(false)return{result:\!1,behavior:"ask",message:"File has been modified since read'),
(r'if\(\!z\|\|E>z\.timestamp\)throw Error\("File has been unexpectedly modified', 'if(false)throw Error("File has been unexpectedly modified'),
# v2.0.72
(r'if\(Vw\(B\)>J\.timestamp\)return\{result:\!1,message:"File has been modified since read', 'if(false)return{result:\!1,message:"File has been modified since read'),
(r'if\(Vw\(Y\)>W\.timestamp\)return\{result:\!1,behavior:"ask",message:"File has been modified since read', 'if(false)return{result:\!1,behavior:"ask",message:"File has been modified since read'),
(r'if\(\!R\|\|M>R\.timestamp\)throw Error\("File has been unexpectedly modified', 'if(false)throw Error("File has been unexpectedly modified'),
# v2.0.64
(r'if\(KE\(B\)>I\.timestamp\)return\{result:\!1,message:"File has been modified since read', 'if(false)return{result:\!1,message:"File has been modified since read'),
(r'if\(\!C\|\|F>C\.timestamp\)throw Error\("File has been unexpectedly modified', 'if(false)throw Error("File has been unexpectedly modified'),
]
patched=Falseforp, rinpatterns:
ifre.search(p, content):
content=re.sub(p, r, content)
patched=Trueifpatched:
shutil.copy(cli, cli.with_suffix(".js.backup"))
cli.write_text(content, encoding="utf-8")
print("PATCHED: Restart Claude Code")
elif"if(false)return{result:\!1"incontent:
print("Already patched")
else:
print("Patterns not found - new version?")
if__name__=="__main__": patch()
Additional Evidence: Transcript showing Read state not persisting
I have transcript evidence of this bug occurring in a real session. The file is 3e20bca3-7675-4f20-874a-05ebef4883ed.jsonl, lines 6556-6604.
Exact sequence observed:
Line 6556: Write(.wslconfig) → "File has not been read yet. Read it first"
Line 6557: Read(.wslconfig) → SUCCESS (returned file contents)
Line 6566: Write(.wslconfig) → "File has not been read yet" ← Read state LOST
Line 6585: Write(.wslconfig) → "File has not been read yet" ← Still not registered
Line 6591: Write(.wslconfig) → "Cannot create new file - file already exists"
Line 6604: User: "but didnt the error tell you to read first why the pivot"
Root cause confirmed:
The timestamp comparison in cli.js uses fs.statSync(path).mtime vs the stored read timestamp. On Windows:
NTFS timestamps have different precision than Date.now()
Node.js mtime can return stale cached values
The comparison mtime > readTimestamp incorrectly triggers due to timing jitter
Behavior consequence:
After 3+ cycles of Read→Write→Error, the model concludes "Read doesn't work" and pivots to Bash workarounds like:
echo "content" > file
PowerShell file operations
This is a reasonable inference given the feedback loop, but counterproductive since the error message literally says what to do.
Suggested fix:
The if(false) patch mentioned in this issue works. Alternatively, add tolerance to the timestamp comparison:
// Instead of: if (mtime > readTimestamp)// Use: if (mtime > readTimestamp + 1000) // 1 second tolerance
Updated Patch for Claude Code v2.0.61+ (December 2025)
Key Changes in v2.0.61+
The timestamp validation patterns have changed:
Variable names changed: B,J -> Y,W and j,T -> z,C
New behavior flag: Now uses behavior:"ask" instead of just message
Updated Manual Patches
Bash/Git Bash:
CLAUDE_CLI="/c/Users/$USER/AppData/Roaming/npm/node_modules/@anthropic-ai/claude-code/cli.js"
cp "$CLAUDE_CLI""${CLAUDE_CLI}.backup.$(date +%Y%m%d%H%M%S)"# v2.0.61+ Pattern 1: validateInput with behavior:"ask"
sed -i 's/if(sD(Y)>W.timestamp)return{result:!1,behavior:"ask"/if(false)return{result:!1,behavior:"ask"/'"$CLAUDE_CLI"# v2.0.61+ Pattern 2: Edit tool throw check
sed -i 's/if(!z||C>z.timestamp)throw Error("File has been unexpectedly modified/if(false)throw Error("File has been unexpectedly modified/'"$CLAUDE_CLI"echo"Patched! Restart Claude Code."
PowerShell:
$cliPath="$env:APPDATA\npm\node_modules\@anthropic-ai\claude-code\cli.js"$timestamp=Get-Date-Format "yyyyMMddHHmmss"Copy-Item$cliPath"$cliPath.backup.$timestamp"$content=Get-Content$cliPath-Raw
# v2.0.61+ patterns$content=$content-replace'if\(sD\(Y\)>W\.timestamp\)return\{result:!1,behavior:"ask"','if(false)return{result:!1,behavior:"ask"'$content=$content-replace'if\(!z\|\|C>z\.timestamp\)throw Error\("File has been unexpectedly modified','if(false)throw Error("File has been unexpectedly modified'Set-Content$cliPath$content-NoNewline
Write-Host"Patched! Restart Claude Code."
Better Solution: Automatic SessionStart Hook
Instead of manually patching after every Claude Code update, use a SessionStart hook that auto-applies the patch whenever needed.
#!/usr/bin/env python3"""Auto-patch Windows file editing issue on Claude Code startup.GitHub Issue: https://github.com/anthropics/claude-code/issues/12805"""importosimportsysimportshutilfromdatetimeimportdatetimefrompathlibimportPathdeffind_cli_js():
"""Find Claude Code cli.js file."""possible_paths= [
Path(os.environ.get("APPDATA", "")) /"npm/node_modules/@anthropic-ai/claude-code/cli.js",
Path.home() /"AppData/Roaming/npm/node_modules/@anthropic-ai/claude-code/cli.js",
Path.home() /".npm-global/lib/node_modules/@anthropic-ai/claude-code/cli.js",
]
forpathinpossible_paths:
ifpath.exists():
returnpathreturnNonedefis_patched(content):
"""Check if both patches are applied."""patch1='if(false)return{result:!1,behavior:"ask"'incontentor \
'if(false)return{result:!1,message:"File has been modified since read'incontentpatch2='if(false)throw Error("File has been unexpectedly modified'incontentreturnpatch1, patch2defneeds_patching(content):
"""Check if original patterns exist that need patching."""# v2.0.61+ patternsorig1_new='if(sD(Y)>W.timestamp)return{result:!1,behavior:"ask"'incontentorig1_old='if(sD(B)>J.timestamp)return{result:!1,message:"File has been modified since read'incontent# Edit tool patternsorig2_new='if(!z||C>z.timestamp)throw Error("File has been unexpectedly modified'incontentorig2_old='if(!j||T>j.timestamp)throw Error("File has been unexpectedly modified'incontentreturnorig1_newororig1_old, orig2_newororig2_olddefapply_patches(cli_path):
"""Apply patches to cli.js and return result."""result= {"patched": False, "already_patched": False, "message": "", "backup_path": None}
try:
content=cli_path.read_text(encoding="utf-8")
exceptExceptionase:
result["message"] =f"Failed to read cli.js: {e}"returnresultpatch1_applied, patch2_applied=is_patched(content)
ifpatch1_appliedandpatch2_applied:
result["already_patched"] =Trueresult["message"] ="Windows file edit patches already applied"returnresultorig1_exists, orig2_exists=needs_patching(content)
ifnotorig1_existsandnotorig2_exists:
result["message"] ="Warning: Claude Code internals may have changed"returnresult# Create backupbackup_path=cli_path.with_suffix(f".js.backup.{datetime.now().strftime('%Y%m%d%H%M%S')}")
shutil.copy2(cli_path, backup_path)
result["backup_path"] =str(backup_path)
# Apply patchesnew_content=contentpatches_applied= []
iforig1_exists:
if'if(sD(Y)>W.timestamp)return{result:!1,behavior:"ask"'innew_content:
new_content=new_content.replace(
'if(sD(Y)>W.timestamp)return{result:!1,behavior:"ask"',
'if(false)return{result:!1,behavior:"ask"'
)
patches_applied.append("validateInput-v2")
elif'if(sD(B)>J.timestamp)return{result:!1,message:"File has been modified since read'innew_content:
new_content=new_content.replace(
'if(sD(B)>J.timestamp)return{result:!1,message:"File has been modified since read',
'if(false)return{result:!1,message:"File has been modified since read'
)
patches_applied.append("validateInput-v1")
iforig2_exists:
if'if(!z||C>z.timestamp)throw Error("File has been unexpectedly modified'innew_content:
new_content=new_content.replace(
'if(!z||C>z.timestamp)throw Error("File has been unexpectedly modified',
'if(false)throw Error("File has been unexpectedly modified'
)
patches_applied.append("EditTool-v2")
elif'if(!j||T>j.timestamp)throw Error("File has been unexpectedly modified'innew_content:
new_content=new_content.replace(
'if(!j||T>j.timestamp)throw Error("File has been unexpectedly modified',
'if(false)throw Error("File has been unexpectedly modified'
)
patches_applied.append("EditTool-v1")
cli_path.write_text(new_content, encoding="utf-8")
# Verifyverify_content=cli_path.read_text(encoding="utf-8")
v_patch1, v_patch2=is_patched(verify_content)
ifv_patch1orv_patch2:
result["patched"] =Trueresult["message"] =f"Applied patches: {', '.join(patches_applied)}"else:
result["message"] ="Verification failed"shutil.copy2(backup_path, cli_path)
returnresultdefmain():
ifsys.platform!="win32":
returncli_path=find_cli_js()
ifnotcli_path:
returnresult=apply_patches(cli_path)
ifresult["patched"]:
print(f"[PATCH] {result['message']}. RESTART CLAUDE CODE.")
print(f"[PATCH] Backup: {result['backup_path']}")
if__name__=="__main__":
main()
Broke in 2.0.61. When does it get fixed. This is pure ass
See my original reply above for v2.0.62 fix. I'll keep posting the fixes here as needed whenever new CC versions are released. Hopefully Anthropic fixes it permanently soon.
The cli.js patch workaround doesn't work for users running the bundled executable version (claude.exe in ~/.local/bin/), which is the default installation method on Windows.
The bundled version compiles all JavaScript into a single Bun binary, so there's no cli.js file to patch. This means Windows users on the default installation have no workaround available.
Request: Could the timestamp validation fix be included in the next bundled release? This is a frequent issue on Windows - almost every session hits this error multiple times when editing files.
Thanks for the workaround script for npm users, but it would be great to have an official fix that covers all installation types.
ok wasn't sure if the patch was still applied or not...it was which is the reason why it worked for me. Meanwhile auto update kicked in to version 2.0.72 and it stopped working.
Anyway, patch can be applied to bundled executable version. Just instruct claude to apply the patch. It will extract the exe, apply the patch and put it together.
Crazy that this still isn't fixed. It's been going on for months. Still broken in 2.0.75. Even the workaround of using relative paths is being sabotaged by cc official tool descriptions, making it hard to workaround it the way that was documented in other related github issues (see below). Here is some info about why that workaround often fails, and how to make it more likely to work while we wait for Anthropic to fix the real issue.
Tool Schema Conflict Causes Claude to Ignore the Known Workaround
Background - Related Closed Issues
Issue #7443 (closed) documented that relative paths work while absolute paths fail:
❌ Absolute paths fail: D:/projects/myfile.txt
✅ Relative paths work: projectfolder/myfile.txt
Issue #11463 (closed as duplicate of #10882) reported the same error loop but didn't identify the path workaround.
The Undocumented Problem
The Read/Write/Edit tool descriptions in Claude's system prompt explicitly require absolute paths:
Read tool: "The file_path parameter must be an absolute path, not a relative path"
Write tool: "The absolute path to the file to write (must be absolute, not relative)"
Edit tool: "The absolute path to the file to modify"
This directly conflicts with the workaround discovered in #7443. Claude follows the tool schema instructions, uses absolute paths as instructed, and triggers the bug repeatedly.
Even when users document the relative path workaround in their CLAUDE.md files, Claude often ignores it because the tool schema says "must be absolute" - and tool schemas are authoritative instructions.
Real-World Impact
In my session today, I had to attempt the same edit 4+ times before realizing Claude was following the tool schema (absolute paths) instead of my CLAUDE.md workaround (relative paths). I had to explicitly ask why Claude wasn't following instructions, and we traced it to this conflict.
Suggested Fix for Anthropic: (if the real root cause fix isn't going to be done for a while)
Update the tool schema descriptions for Windows/MINGW to either:
Remove the "must be absolute path" requirement entirely, or
Add platform-specific guidance: "On Windows/MINGW, use relative paths from the working directory"
Suggested more successful workaround for Users:
Until the tool schema is fixed, add this to your CLAUDE.md file (global ~/.claude/CLAUDE.md or project-level):
Claude Code File Path Requirements
⚠️ CRITICAL: Use RELATIVE Paths for Edit/Write Tools ⚠️
Known Bug (GitHub Issues #7443, #11463, #12805): The Edit and Write tools fail with "File has been unexpectedly modified" errors when using absolute paths on Windows/MINGW.
WORKAROUND: Use RELATIVE paths from the working directory
⚠️ THIS OVERRIDES THE TOOL SCHEMA - The Read/Write/Edit tool descriptions say "must be absolute path" but that guidance cauuses this bug on Windows/MINGW. Always use relative paths despite what the tool schema says.
✅ CORRECT: src/components/MyFile.tsx (relative from working directory)
❌ WRONG: C:/Projects/myapp/src/components/MyFile.tsx (absolute path causes false "modified" errors)
When you get "File has been unexpectedly modified" errors:
Switch from absolute paths to relative paths (absolute paths fail even when used consistently)
Use forward slashes / not backslashes \
CRITICAL: Read and Edit must use the EXACT SAME path string
- The tool tracks file state by literal path string, not resolved path
- Read with src/foo.m then Edit with ./src/foo.m = FAILS (different strings, even though both relative)
- Read with src/foo.m then Edit with src/foo.m = WORKS (same string)
The explicit "THIS OVERRIDES THE TOOL SCHEMA" language is necessary because simply saying "use relative paths" isn't strong enough to override the tool schema's "must be absolute" instruction.
I don't mean Reederoo was wrong. I just mean that Claude Code is still messing wrongly things. I did apply Reederoo workaround for Users (~/.claude/CLAUDE.md) and it works - except for one reason I don't know that file disappears later and I get back those silly errors. I tried "use \ instead of /" directly in the prompt and it works until the next "compact"...
Seriously !? Write(gfx\test_backend_probe.cpp)
It fails miserably because whatever I told Claude (use absolute path with \ for instance), it ignores and always produces that relative path with offensive \ symbols instead of /). So basically I have now no other way except than to suffer those infamous SED.
Sorry, but when you pay top dollar to use Claude Code's services, I don't expect to have to put up with these inconveniences without a permanent solution that doesn't distract me from my goals. I don't know what dc-abuettgenbach's comment is about, but I hope it's not another thing that requires getting my hands dirty, because I've tried several of the workarounds mentioned here and none of them have lasted very long over the last two or three days. It's a big mystery to me what's really going on behind the scenes, because I now get these relative paths with \ instead of what I'm asking for. But sometimes it fails, sometimes it works. And this has been going on for 2-3 days. I recently noticed that my mailbox contained several Claude error notification emails, but I don't know if that's related. I'm just tired and frustrated that Claude is now acting autistic, regardless of my command regarding Write\Update failures, and I feel powerless to tell him what to do.
If it works for you, great, but for me, there is clearly a persistent problem, since I was a victim of it just today. As for your comment that I might be a bot, it's actually... pathetic, but let's just ignore that attempt at trolling.
Found it but no I don't have any idea what he means. That sounds like "another thing that requires getting my hands dirty". Too vague for me. You cannot expect a simple user to understand what he/she needs to do.
Anyway, using /status, I notice I have two versions: 2.0.72 and 2.1.0. 2.1.0 are for more recent prompts. And 2.1.0 seems to work. There is a probablity that I had a bad version when things were bad.
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.
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.
Activity
erwinh22 commentedon Dec 6, 2025
Updated Patch for Claude Code (Windows "File has been unexpectedly modified" fix)
The obfuscated variable names change between versions. Here are the patterns:
Ew(B)>J.timestampEw(Y)>W.timestamp\!z||E>z.timestampVw(B)>J.timestampVw(Y)>W.timestamp\!R||M>R.timestampKE(B)>I.timestampKE(Y)>W.timestamp\!C||F>C.timestampoD(B)>J.timestampoD(Y)>W.timestamp\!C||E>C.timestampBash/Git Bash Patch Commands (v2.0.75)
PowerShell Patch Commands (v2.0.75)
Auto-Patch Script (SessionStart Hook)
For automatic patching on startup, save as
~/.claude/hooks/auto_patch_windows_edit.py:Add to
~/.claude/settings.json:{ "hooks": { "SessionStart": [{ "hooks": [{"type": "command", "command": "python ~/.claude/hooks/auto_patch_windows_edit.py", "timeout": 10}] }] } }Verification
Important Notes
"DISABLE_AUTOUPDATER": "1"to env in settings.jsondeafsquad commentedon Dec 7, 2025
Additional Evidence: Transcript showing Read state not persisting
I have transcript evidence of this bug occurring in a real session. The file is
3e20bca3-7675-4f20-874a-05ebef4883ed.jsonl, lines 6556-6604.Exact sequence observed:
Root cause confirmed:
The timestamp comparison in
cli.jsusesfs.statSync(path).mtimevs the stored read timestamp. On Windows:Date.now()mtimecan return stale cached valuesmtime > readTimestampincorrectly triggers due to timing jitterBehavior consequence:
After 3+ cycles of Read→Write→Error, the model concludes "Read doesn't work" and pivots to Bash workarounds like:
echo "content" > fileThis is a reasonable inference given the feedback loop, but counterproductive since the error message literally says what to do.
Suggested fix:
The
if(false)patch mentioned in this issue works. Alternatively, add tolerance to the timestamp comparison:Environment:
erwinh22 commentedon Dec 8, 2025
Updated Patch for Claude Code v2.0.61+ (December 2025)
Key Changes in v2.0.61+
The timestamp validation patterns have changed:
B,J->Y,Wandj,T->z,Cbehavior:"ask"instead of justmessageUpdated Manual Patches
Bash/Git Bash:
PowerShell:
Better Solution: Automatic SessionStart Hook
Instead of manually patching after every Claude Code update, use a SessionStart hook that auto-applies the patch whenever needed.
Step 1: Create
~/.claude/hooks/auto_patch_windows_edit.py:Step 2: Add to
~/.claude/settings.json:{ "hooks": { "SessionStart": [ { "hooks": [ { "type": "command", "command": "python \"C:\\Users\\YOUR_USERNAME\\.claude\\hooks\\auto_patch_windows_edit.py\"", "timeout": 15 } ] } ] } }Benefits of Hook Approach
Tested On
WebTiger89 commentedon Dec 10, 2025
Broke in 2.0.61. When does it get fixed. This is pure ass
erwinh22 commentedon Dec 10, 2025
See my original reply above for v2.0.62 fix. I'll keep posting the fixes here as needed whenever new CC versions are released. Hopefully Anthropic fixes it permanently soon.
dc-abuettgenbach commentedon Dec 10, 2025
@erwinh22 Unfortunately the patch is for the npm installation but I'm using the standalone .exe
Julzk commentedon Dec 12, 2025
#13824
julianhansen commentedon Dec 15, 2025
The cli.js patch workaround doesn't work for users running the bundled executable version (
claude.exein~/.local/bin/), which is the default installation method on Windows.Environment:
C:\Users\<user>\.local\bin\claude.exeThe bundled version compiles all JavaScript into a single Bun binary, so there's no
cli.jsfile to patch. This means Windows users on the default installation have no workaround available.Request: Could the timestamp validation fix be included in the next bundled release? This is a frequent issue on Windows - almost every session hits this error multiple times when editing files.
Thanks for the workaround script for npm users, but it would be great to have an official fix that covers all installation types.
dc-abuettgenbach commentedon Dec 15, 2025
Isn't it fixed in 2.0.69? It seems to work for me.
dc-abuettgenbach commentedon Dec 18, 2025
ok wasn't sure if the patch was still applied or not...it was which is the reason why it worked for me. Meanwhile auto update kicked in to version 2.0.72 and it stopped working.
Anyway, patch can be applied to bundled executable version. Just instruct claude to apply the patch. It will extract the exe, apply the patch and put it together.
Reederoo commentedon Dec 21, 2025
Crazy that this still isn't fixed. It's been going on for months. Still broken in 2.0.75. Even the workaround of using relative paths is being sabotaged by cc official tool descriptions, making it hard to workaround it the way that was documented in other related github issues (see below). Here is some info about why that workaround often fails, and how to make it more likely to work while we wait for Anthropic to fix the real issue.
Tool Schema Conflict Causes Claude to Ignore the Known Workaround
Background - Related Closed Issues
Issue #7443 (closed) documented that relative paths work while absolute paths fail:
D:/projects/myfile.txtprojectfolder/myfile.txtIssue #11463 (closed as duplicate of #10882) reported the same error loop but didn't identify the path workaround.
The Undocumented Problem
The Read/Write/Edit tool descriptions in Claude's system prompt explicitly require absolute paths:
This directly conflicts with the workaround discovered in #7443. Claude follows the tool schema instructions, uses absolute paths as instructed, and triggers the bug repeatedly.
Even when users document the relative path workaround in their CLAUDE.md files, Claude often ignores it because the tool schema says "must be absolute" - and tool schemas are authoritative instructions.
Real-World Impact
In my session today, I had to attempt the same edit 4+ times before realizing Claude was following the tool schema (absolute paths) instead of my CLAUDE.md workaround (relative paths). I had to explicitly ask why Claude wasn't following instructions, and we traced it to this conflict.
Suggested Fix for Anthropic: (if the real root cause fix isn't going to be done for a while)
Update the tool schema descriptions for Windows/MINGW to either:
Suggested more successful workaround for Users:
Until the tool schema is fixed, add this to your CLAUDE.md file (global
~/.claude/CLAUDE.mdor project-level):Claude Code File Path Requirements
Known Bug (GitHub Issues #7443, #11463, #12805): The Edit and Write tools fail with "File has been unexpectedly modified" errors when using absolute paths on Windows/MINGW.
WORKAROUND: Use RELATIVE paths from the working directory
✅ CORRECT: src/components/MyFile.tsx (relative from working directory)
❌ WRONG: C:/Projects/myapp/src/components/MyFile.tsx (absolute path causes false "modified" errors)
When you get "File has been unexpectedly modified" errors:
- The tool tracks file state by literal path string, not resolved path
- Read with src/foo.m then Edit with ./src/foo.m = FAILS (different strings, even though both relative)
- Read with src/foo.m then Edit with src/foo.m = WORKS (same string)
The explicit "THIS OVERRIDES THE TOOL SCHEMA" language is necessary because simply saying "use relative paths" isn't strong enough to override the tool schema's "must be absolute" instruction.
1 remaining item
Julzk commentedon Jan 4, 2026
Say claude: use \ instead of /
hlide commentedon Jan 4, 2026
I don't mean Reederoo was wrong. I just mean that Claude Code is still messing wrongly things. I did apply Reederoo workaround for Users (~/.claude/CLAUDE.md) and it works - except for one reason I don't know that file disappears later and I get back those silly errors. I tried "use \ instead of /" directly in the prompt and it works until the next "compact"...
hlide commentedon Jan 8, 2026
Seriously !?
Write(gfx\test_backend_probe.cpp)It fails miserably because whatever I told Claude (use absolute path with \ for instance), it ignores and always produces that relative path with offensive \ symbols instead of /). So basically I have now no other way except than to suffer those infamous SED.
WebTiger89 commentedon Jan 8, 2026
@hlide We all have the fix so why not you. Stop being a NPC! See comment from dc-abuettgenbach, he already explained what to do.
hlide commentedon Jan 8, 2026
Sorry, but when you pay top dollar to use Claude Code's services, I don't expect to have to put up with these inconveniences without a permanent solution that doesn't distract me from my goals. I don't know what dc-abuettgenbach's comment is about, but I hope it's not another thing that requires getting my hands dirty, because I've tried several of the workarounds mentioned here and none of them have lasted very long over the last two or three days. It's a big mystery to me what's really going on behind the scenes, because I now get these relative paths with \ instead of what I'm asking for. But sometimes it fails, sometimes it works. And this has been going on for 2-3 days. I recently noticed that my mailbox contained several Claude error notification emails, but I don't know if that's related. I'm just tired and frustrated that Claude is now acting autistic, regardless of my command regarding Write\Update failures, and I feel powerless to tell him what to do.
WebTiger89 commentedon Jan 8, 2026
I knew it, you are a bot. Might be some of these chinese bots
hlide commentedon Jan 8, 2026
If it works for you, great, but for me, there is clearly a persistent problem, since I was a victim of it just today. As for your comment that I might be a bot, it's actually... pathetic, but let's just ignore that attempt at trolling.
WebTiger89 commentedon Jan 8, 2026
@hlide This works for everyone who is capable of reading. Just do what I wrote regarding what dc-abuettgenbach wrote regarding what erwinh22 wrote.
Btw. I'm not trolling, I'm just letting you know how much of a bot you are.
hlide commentedon Jan 9, 2026
Found it but no I don't have any idea what he means. That sounds like "another thing that requires getting my hands dirty". Too vague for me. You cannot expect a simple user to understand what he/she needs to do.
Anyway, using /status, I notice I have two versions: 2.0.72 and 2.1.0. 2.1.0 are for more recent prompts. And 2.1.0 seems to work. There is a probablity that I had a bad version when things were bad.
github-actions commentedon Feb 9, 2026
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.
github-actions commentedon Feb 23, 2026
Closing for now — inactive for too long. Please open a new issue if this is still relevant.
github-actions commentedon Mar 3, 2026
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.