Claude Code: "String to replace not found in file"
Claude Code Last checked 2026-10-14
The Edit tool does an exact character-for-character match, and the text it is searching for no longer matches the file — usually because the file changed since it was read, or because whitespace, indentation or invisible characters differ. Make it re-read the file immediately before editing, and have it edit a short unique anchor rather than a long block.
What you saw
An edit fails with Error: String to replace not found in file (or old_string not found), and the agent either retries with a slightly different block or gives up and rewrites the whole file.
Sometimes it fails repeatedly on the same edit while insisting the text is there — and when you look, the text *is* there.
What it actually means
Edit is not a fuzzy patch tool. It finds one exact occurrence of old_string and replaces it. Anything that changes the bytes breaks the match.
The usual causes, in order of how often they actually bite:
- The file moved under it. Your formatter ran on save, a linter auto-fixed, a hot-reload wrote to the file, or you edited it yourself while the agent was thinking. The agent is matching against the version it read earlier.
- Whitespace. Tabs vs spaces, two-space vs four-space indentation, trailing spaces, or
\r\n line endings on a repo that was checked out on Windows. - Not unique, or not present. The agent reconstructed the snippet from memory of a previous conversation turn instead of from a fresh read.
- Invisible characters. Smart quotes, non-breaking spaces and zero-width characters pasted in from a doc or a webpage look identical in your editor and are different bytes.
The fix
Tell it to re-read first. This clears a stale-context failure in one turn:
Re-read the file with the Read tool right now, then make the edit based only on what you just read.
Shrink the anchor. A long block has many more chances to mismatch than one distinctive line. Ask for a minimal unique anchor:
Use the shortest unique string you can find as old_string — ideally a single line. Do not paste a large block.
Turn off format-on-save while an agent is working the same files. That single setting causes more of these failures than anything else.
Normalise line endings if the repo is mixed:
git config core.autocrlf false
printf '* text=auto eol=lf\n' >> .gitattributes
If it has failed twice on the same edit, stop it rewriting the file wholesale. A full rewrite is how working code gets silently dropped:
Do not rewrite the file. Show me the exact old_string you are trying to match and the matching lines from the file, and stop.
How to stop it happening again
Keep a clean git tree while the agent works. git diff after every accepted edit turns a mystery into a one-second check.
Put the project's indentation and line-ending rules in CLAUDE.md at the repo root so they are in context on every run.
Do not hand-edit the same file the agent is editing. Pick one writer at a time.
Prefer several small edits over one large one. Small edits fail loudly and cheaply; large ones fail after the agent has already decided to rewrite.
Related questions
The text is definitely in the file. Why does it still fail?
Almost always whitespace or invisible characters. Check for tabs vs spaces and for smart quotes or non-breaking spaces pasted from a document. Your editor renders them identically; the matcher does not.
Should I just let it rewrite the whole file?
No. A wholesale rewrite from context is where unrelated working code gets dropped. Make it re-read and retry with a smaller anchor instead.
Does this mean my file is corrupted?
No. It is a failed string match, not a file error. Nothing has been written.