[BUG] Too many edit file errors

Open 💬 55 comments Opened Jul 14, 2025 by junaid1460

Environment

  • Platform (select one):
  • [x] Anthropic API
  • [ ] AWS Bedrock
  • [ ] Google Vertex AI
  • [x] Other: Claude Max
  • Claude CLI version: 1.0.51 (Claude Code)
  • Operating System: Mac 15.0.1
  • Terminal: Vscode Integrated terminal, zsh

Bug Description

Claude makes too many edit file errors, reads, file and then again makes error, after few errors, gives up and says all okay if it builds

Steps to Reproduce

Some long conversation

Expected Behavior

Of course for to edit without error

Actual Behavior

⎿ Error: String to replace not found in file.
lots of it

Additional Context

Earlier when versions were below 1.0.30 it was all good, latest is just more dumb

View original on GitHub ↗

55 Comments

junaid1460 · 1 year ago

Latest versions:

  • They add place holders and report everything working
  • Just too eager to fix linting issue and report success. ( This is happening way too much )
junaid1460 · 1 year ago

Also when the content that cli has to show is longer than terminal height, it's like hacker movie, keeps flashing whole content over and over again

jgspratt · 11 months ago

I get a lot of Error editing file messages which eventually succeed. I'm going to close https://github.com/anthropics/claude-code/issues/6075 in favor of this one (3471). Just to be clear:

Bug Description

A perfectly writable file threw Error editing file with no further explanation and no error logs that I could find. Claude ended up going on to edit that file without needing to be re-prompted.

Steps to Reproduce

  1. Ask Claude to edit a file

Expected Behavior

  1. No error messages, Claude was able to edit file
  2. Or, if Claude couldn't edit the file, and there was an error message, an explanation or a pointer to an error log with detailed logs

Actual Behavior

Bland error message (no details or info on how to get details); Claude was able to edit the file.

jgspratt · 11 months ago

Here's a literal (redacted) example:

● Now let me update file.py to remove the ... code and simplify it:

  Update(path/to/file.py)
  ⎿  Error editing file

● Let me read the current state of file.py first:

● Read(path/to/file.py)
  ⎿  Read 189 lines (ctrl+r to expand)

● Now let me replace the entire ... logic in file.py:

  Update(path/to/file.py)
  ⎿  Error editing file

● Let me use Write to completely replace file.py:
pujan789 · 11 months ago

Any updates on this error?

shukebeta · 11 months ago

Tell claude code this "avoid using Read/Update tool, as they are broken for some reason, use an alternative instead." and then it will use cat to read files and use sed to update files in gitbash. @pujan789 @jgspratt

starbaser · 11 months ago

This might be related #6148

/home/dgnsrekt/.nvm/versions/node/v24.4.1/lib/node_modules/@anthropic-ai/claude-code/vendor/ripgrep/arm64-linux ./rg --version : Unsupported system page size : Unsupported system page size memory allocation of 160 bytes failed [1] 838220 IOT instruction (core dumped) ./rg --version It looks like there is an issue with the rg that is bundled with claude-code.

if ripgrep is used to rg --files command files, I'm going to make a guess that it's main purpose is for search/replace when updating files. Perhaps the model has to recreate the exact text that the update tool demands and fails multiple times to do so.

A potential fix could be USE_BUILTIN_RIPGREP:

Use built-in ripgrep by default; to opt out of this behavior, set USE_BUILTIN_RIPGREP=0

---

Tell claude code this "avoid using Read/Update tool, as they are broken for some reason, use an alternative instead." and then it will use cat to read files and use sed to update files in gitbash. @pujan789 @jgspratt

An mcp tool like this or downgrading is also an alternative:

npm install -g @anthropic-ai/claude-code@1.0.83 --force

See here for the version history

kostyay · 10 months ago

Same issue on my end

starbaser · 10 months ago

I haven't had issues since disabling the builtin ripgrep

davidaparicio · 10 months ago

!Image

I'm also experiencing that problem very (too) frequent on my mac, with the latest version (1.0.88 (Claude), hopefully it will be fixed soon!

dcarey · 10 months ago

Same issue here

starbaser · 10 months ago

Add this to ~/.claude/settings.json:

"env": {
    "USE_BUILTIN_RIPGREP": "0"
  },

In order to confirm if this works please react with a thumbs up/down to this comment

gyanraj06 · 10 months ago
"USE_BUILTIN_RIPGREP": "0"

my vscode says it's not allowed

starbaser · 10 months ago
> "USE_BUILTIN_RIPGREP": "0" my vscode says it's not allowed

sure, try it without vscode then

gyanraj06 · 10 months ago
> > "USE_BUILTIN_RIPGREP": "0" > > > my vscode says it's not allowed sure, try it without vscode then

Thanks. the code was working - but unfortunately still i have error editing file error. hope it get fixed by dev soon.

codeman101 · 10 months ago

I hope this issue gets fixed. Forcing the older version to install is a good temporary fix but i actually discovered the issue exists in both versions it just takes a lot longer to happen on the older version. I believe it's an issue with the session going for too long because starting a new session fixes the issue.

gyanraj06 · 10 months ago

is someone from claude looking into this issue? we're paying shit load of money for this feature and even after month i have the same - error editing file issue.

junaid1460 · 10 months ago

They need to do something like what cursor does, have a relatively small model do the edits. Because update tool works based on diff apply mechanism if it finds multiple items then it would not update, that time claude has to read current state and then give more before and after text to match that part exactly or set replace to true. it kind of mainly happens because claude assumes it has read something and then just replaces with full confidence, because there are these optimisations like reading only 50 lines and crap claude is probably ignoring the fact that it hasn't read the file completely. basically claude has to be really good at needle in the haystack problem, which is no models right now are good at 100%. So over time when claude edits contents change as per these edits, original read content and then what go replaced / failed etc etc, so LLM must do these replaces in its weights to figure out the right version right now.

Possible solutions I can think of is:

  1. Deliberately help model activate the right paths ( Not sure, but usually claude does better job if I remind it, eg: remember the CLAUDE.md rules. when it starts doing something is declared as anti-pattern in claude md)
> Assistant: Let me update the file

if Model is gonna call tool update tool ?
    add Assistant: Considering all the changes I have made till now
    ^ this could help model understand what all things it should be cosidering
else
   noop

> Update(....)
  1. Take whatever claude is trying to update and then pass it to Write small 3b -7b model which is trained heavily on Update(..) tool call. For this anthropic must already have hude dataset to fine tune.
ie: 
Update(context, Diff, file) -> 
      content = ReadFile(file)
      updated_content = UpdateWithSmallModel(Take(context, last few message), Diff, content)
      case Write(updated_content, file)
           ok => "Yes, done"
           error => error
     
  
teito-dev · 10 months ago

This is a huge issue, how is this not priority 1 for anthropic ?

jgspratt · 10 months ago

I've noticed this happens most often (only?) when my pre-commit hooks run (or VSCode auto reformats) and reformat files. I think Claude is keeping track of (maybe?) hashes of files since last edit, and if it tries to edit a file that has an updated hash, it fails and needs to re-read the file. Not sure why it needs to fail multiple times sometimes though.

fatihaziz · 9 months ago

its also bugging me because all of those failures edit cost us tokens.
its slashing performance

fatihaziz · 9 months ago

i think we can get the error reason after pressing Ctrl+O
"⎿ Error: No changes to make: old_string and new_string are exactly the same."

now it become clearer why, i hope its the default response shown without any need to press Ctrl+O

mrwiora · 9 months ago

experienced the same today with usage via copilot

chkoc · 9 months ago

i still experience this in every session. claude code running in powershell.

example:
● Update(src\model\SomeService.java)
⎿  Error editing file

● Read(src\model\SomeService.java)
⎿  Read 235 lines

● Update(src\model\SomeService.java)
⎿  Updated src\model\SomeService.java with 5 additions and 1 removal

jasonswearingen · 9 months ago

i still get this problem, all the time over the last couple days.

abgagu · 8 months ago

This makes it impossible to use this tool: consuming context incessantly by reading the same lines over and over again, trying to edit them until it has to compact the conversation, losing almost all the context of the initial instructions. And then, it starts all over again.

The eternal nonsense of the file being edited since it was read.

<img width="853" height="805" alt="Image" src="https://github.com/user-attachments/assets/b6e15437-1b02-4bb1-ae21-8a05cfc6af37" />

bitbeamer · 8 months ago

I found a really good solution: codex
Bye, bye, Claude

jasonswearingen · 8 months ago

this is a crippling bug. very surprised and sad that anthropic lets this problem go on for so long. makes claude code literally unusable.

my "solution" was to write a custom mcp. You can too, just tell claude code to create a file-edit-mcp with tools that exactly match it's built-in edit tool. it'll waste a few hours of your time, but lets this product actually be useful again.

xrf-9527 · 8 months ago

Root Cause Analysis: Edit Tool Failures Due to Whitespace Handling

Reproduction

I consistently encountered "Error editing file" failures when attempting to use the Edit tool on files with tab indentation. The pattern was:

  1. Read file successfully using Read tool
  2. Attempt Edit with exact string copied from Read output → Fail
  3. Retry with different context strings → Fail repeatedly
  4. Eventually resorted to Write tool to rewrite entire file → Success

Root Cause Investigation

After multiple Edit failures, I investigated the actual file content using od -c (macOS) and discovered:

The issue: Tab characters in file indentation

$ od -c <file> | head
0000000 \t \t \t r e t u r n { \n \t \t \t \t
0000020 t r a d e I d : i t e m . t r
0000040 a d e I d , \n \t \t \t \t r e m a r

The problem:

  • The actual file uses tab characters (\t) for indentation
  • When Read tool displays the file, line numbers are prefixed with: <spaces><line_number><tab><content>
  • This makes it visually ambiguous whether indentation uses tabs or spaces
  • The Edit tool's string matching is extremely strict - requires exact whitespace match including every tab/space
  • Even one mismatched whitespace character causes "String to replace not found in file"

Technical Details

Read tool output format misleads about whitespace:
48→ return {
49→ tradeId: item.tradeId,
50→ remark: remarkData,
51→ };

The → after line number is actually a tab, but the content indentation also uses tabs. When copying this text to construct old_string, it's nearly impossible to preserve the exact
whitespace structure.

Why Edit fails but Write succeeds:

  • Edit requires exact string matching including all whitespace
  • Write replaces entire file content, bypassing pattern matching

Suggested Fixes

  1. Improve Read tool output: Add visual indicators for tabs (e.g., display as ⇥ or →) or provide a --show-whitespace option
  2. Relax Edit tool matching: Implement smart whitespace normalization:
  • Option to treat tab as equivalent to N spaces
  • Fuzzy matching mode that ignores leading/trailing whitespace differences
  • Warning when match fails due to whitespace mismatch
  1. Better error messages: When Edit fails, show:

Error: String not found. Possible whitespace mismatch at line X:
Expected: " return {" (4 spaces)
Found: " return {" (2 tabs)

  1. New tool parameter: Add normalize_whitespace: bool parameter to Edit tool

Workaround

For now, the only reliable solution when encountering these errors is:

  • Use Write tool instead of Edit for files with mixed/unclear indentation
  • Or manually inspect file with cat -A (Linux) / od -c (macOS) to identify exact whitespace characters

Environment

  • Claude Code version: Latest (as of 2025-11-05)
  • Platform: macOS
  • File type: JavaScript (.jsx)
  • Indentation: Tabs

This issue severely impacts productivity as Edit tool is fundamental to Claude Code's workflow. The cascading failures waste tokens and user time.

junaid1460 · 8 months ago

this great finding, did you try creating new output style to address this specifically, if not try once

boxed · 8 months ago

On my system Claude tried to read with absolute paths, but for some reason has decided that my username is boxd and not boxed, meaning it always gets the full path (/Users/boxed/Projects/...) wrong (/Users/boxd/Projects/...). This seems to be at least part of Claudes issues with trying to read files and getting errors. But it's not all of it since it also fails with relative paths that look ok.

abgagu · 8 months ago
I found a really good solution: codex Bye, bye, Claude

Sure. I have the Max subscription for Claude because I love some of its features and I use (or used to use) it intensively. But if they don't fix that serious issue soon, I will indeed consider migrating to Codex.

jasonswearingen · 8 months ago

workaround: writing my own file-edit-mcp worked. you could likely use an existing 3rd party file edit mcp the same.

it is a waste of hours though.

Dimonka2 · 7 months ago
npm install -g @anthropic-ai/claude-code@1.0.83 --force

Actually even this works well:
npm install -g @anthropic-ai/claude-code@2.0.36 --force

junaid1460 · 7 months ago

with opus 4.5 it's much better, the model itself is better. It's not good at debugging codex is far ahead in that

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.

boxed · 6 months ago

I got this error just today, so yes it's still a thing.

davidaparicio · 6 months ago

I have the same issue even on the VScode extension.. :/

jasonswearingen · 6 months ago

~~I am not getting the Edit issue anymore, I think it went away around the 2.0.7x timeframe~~

EDIT: I am still seeing the problem, it seems to be because Claude tries to write using / for path separators. when it eventually figures out to use windows specific \ for reads+writes it finally succeeds.

boxed · 6 months ago

Well I checked now, I have 2.0.76, and I got two "Error reading file" errors just a few hours ago. So it didn't fully go away.

junaid1460 · 6 months ago

Error usually happens if

  • I quit claude restart the session
  • After long session and its almost time to compact
  • Auto compact happened in the middle of current task
jasonswearingen · 6 months ago

I am also seeing the problem still, it seems to be because Claude tries to write using / for path separators. when it eventually figures out to use windows specific \ for reads+writes it finally succeeds.

glu000 · 6 months ago

I have the same issue on a Mac. Claude Code tries to edit a file several times. Then it tries to change the file using sed which fails too

Claude Code v2.1.5

<img width="789" height="480" alt="Image" src="https://github.com/user-attachments/assets/d48945e8-0802-43e4-8831-f8a97a3c576a" />

boxed · 6 months ago

I hot this error yesterday and managed to figure out what the issue was then. It tried to insert a piece of code at the end of the file, but instead of just appending, it wanted to insert it after a specific unique string, but the last line of the file was bot unique. It spun around quite a few times because of that.

marcindulak · 5 months ago

Does the unstale bot still work?

junaid1460 · 5 months ago

I think athropic keeping it to avoid making errors, which is okay, I hope anyhropic optimises and drops those failed tool calls, to avoid hitting compaction point quickly

shodiyorbek · 4 months ago

Any updates?

jiayukk · 4 months ago

The command npm install -g @openai/codex is very effective.

ListenToMee · 4 months ago

<img width="1370" height="802" alt="Image" src="https://github.com/user-attachments/assets/065aec3e-d5c8-4d02-b7aa-c5c9f71621ca" />

JohannesDeml · 4 months ago

Tip for now: Try asking claude what went wrong, and then let it write rules for how it should edit files into your cluade.md to make sure it does not repeat those mistakes.

yurukusa · 4 months ago

The "string to replace not found" error typically happens when Claude's context becomes stale — it read the file earlier in the conversation, the file changed (either by Claude or external edits), and now the old_string in the Edit tool doesn't match the current file contents.

Workaround 1: PostToolUse hook to force re-read after failed edits

#!/bin/bash
# ~/.claude/hooks/edit-retry-hint.sh
# PostToolUse — when Edit fails, remind Claude to re-read the file

INPUT=$(cat)
TOOL_NAME=$(echo "$INPUT" | jq -r '.tool_name // empty')

[ "$TOOL_NAME" != "Edit" ] && exit 0

# Check if the tool output contains an error
TOOL_OUTPUT=$(echo "$INPUT" | jq -r '.tool_output // empty')
if echo "$TOOL_OUTPUT" | grep -qi "not found in file\|string to replace"; then
  echo "💡 Edit failed — the file contents have changed since you last read it. Re-read the file with the Read tool before retrying the edit." >&2
fi

exit 0

Workaround 2: CLAUDE.md rule to prevent the pattern

## Edit Tool Rules
- If an Edit fails with "string not found", ALWAYS re-read the file before retrying
- Never attempt the same edit twice without re-reading
- After 2 consecutive Edit failures on the same file, use the Read tool to display the current contents, then construct a new edit based on what you actually see
- Do not "give up and say it builds" — verify the edit actually applied

Workaround 3: Context monitor hook to catch the root cause — long conversations where context gets stale:

#!/bin/bash
# ~/.claude/hooks/context-monitor.sh
# PostToolUse — track tool call count as proxy for context staleness

COUNTER_FILE="/tmp/cc-tool-count-$$"
COUNT=$(cat "$COUNTER_FILE" 2>/dev/null || echo 0)
COUNT=$((COUNT + 1))
echo "$COUNT" > "$COUNTER_FILE"

if [ "$COUNT" -ge 150 ]; then
  echo "⚠️ WARNING: 150+ tool calls in this session. File contents in context may be stale. Use /compact or re-read files before editing." >&2
fi

exit 0

The combination of the CLAUDE.md rule (behavioral) and the PostToolUse hint (structural) significantly reduces the "edit error loop" pattern.

junaid1460 · 4 months ago

It's essentially context rot. from the time I reported this issue it has gotten much much better with better models.
but for me the personal case is I sometimes have long horizon tasks. I figure best way way to do the work is not reach the context rot situation, where compaction

try this https://moltcode.com, I wrote this up for my own pain dealing with claude and codex, very targeted, for sure not for everyone, there will be bugs, if you intend to use it, report the bug to me.

I put myself up on conductor agent in this, such a way that there's primary claude I talk to and understands my problem, then I tell conductor claude that codex is really good at precision edits and claude is really good research that has open ended problems.

So after that claude would use claude and codex well. as sub agents.

If claude still uses claude itself as sub agent, just re-explain it that "Claude, you're really good thinker, codex is really good work horse, don't feel bad about what I said", I am not kidding, claude has some personality.

yurukusa · 3 months ago

Two hooks that mitigate this:
1. Enforce Read before Editread-before-edit.sh (PreToolUse/Edit)
Blocks Edit if the target file hasn't been Read in the current session. Forces Claude to get the exact current content before attempting replacements:

{
  "hooks": {
    "PreToolUse": [{
      "matcher": "Edit",
      "hooks": [{ "type": "command", "command": "bash -c '$(cat <<\"SH\"\nINPUT=$(cat)\nFILE=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\" 2>/dev/null)\n[ -z \"$FILE\" ] && exit 0\nLOG=\"/tmp/cc-read-files-$$\"\nif [ ! -f \"$LOG\" ] || ! grep -qF \"$FILE\" \"$LOG\" 2>/dev/null; then\n  echo \"BLOCKED: Read $FILE first before editing.\" >&2\n  exit 2\nfi\nexit 0\nSH\n)'" }]
    }]
  }
}

2. Detect repeated Edit failuresedit-error-counter.sh (PostToolUse/Edit)
After 3 consecutive "String to replace not found" errors, warns Claude to Read the file again. Catches the loop where Claude keeps guessing at stale content.
Install:

npx cc-safe-setup --install-example read-before-edit
npx cc-safe-setup --install-example edit-error-counter
VGerris · 2 months ago
Two hooks that mitigate this: 1. Enforce Read before Editread-before-edit.sh (PreToolUse/Edit) Blocks Edit if the target file hasn't been Read in the current session. Forces Claude to get the exact current content before attempting replacements: { "hooks": { "PreToolUse": [{ "matcher": "Edit", "hooks": [{ "type": "command", "command": "bash -c '$(cat <<\"SH\"\nINPUT=$(cat)\nFILE=$(echo \"$INPUT\" | jq -r \".tool_input.file_path // empty\" 2>/dev/null)\n[ -z \"$FILE\" ] && exit 0\nLOG=\"/tmp/cc-read-files-$$\"\nif [ ! -f \"$LOG\" ] || ! grep -qF \"$FILE\" \"$LOG\" 2>/dev/null; then\n echo \"BLOCKED: Read $FILE first before editing.\" >&2\n exit 2\nfi\nexit 0\nSH\n)'" }] }] } } 2. Detect repeated Edit failuresedit-error-counter.sh (PostToolUse/Edit) After 3 consecutive "String to replace not found" errors, warns Claude to Read the file again. Catches the loop where Claude keeps guessing at stale content. Install: npx cc-safe-setup --install-example read-before-edit npx cc-safe-setup --install-example edit-error-counter

can you explain in more detail how this works and needs to be setup ?
Is the hook snippet for settings.json ?

I have this issue like others, with Gemma 4.
What do the npx commands do ?

Helps to clarify for starters too, thank you!

stanlrt · 2 months ago

What's worse is that it ignores the warning and assumes the edit worked. This is pretty new behaviour, before it would try again.