TL;DR
TL;DR
This error is caused by exact-match search-replace operating on stale or reformatted code. Reload the file from disk just-in-time, reduce multi-line hunks, temporarily disable format-on-save, and prefer semantic apply. See the report: GitHub issue #968.
If you're building your own application, use Morph's API. If you're using Claude Code, install morphllm.com/mcp.
Symptoms
Claude Code Update output
⏺ Update(../../node/graph_shader.go)…
⎿ Error: String to replace not found in file.
Typically appears after an auto-formatter or a separate tool modified the file between context read and update execution.
Why it happens
- Formatters (e.g.,
go fmt
) change whitespace/newlines. - Editor format-on-save or lint auto-fix rewrites code mid-flight.
- Model-quoted source diverges from on-disk content (stale buffer, concurrency).
- CRLF vs LF or trailing whitespace differences break exact match.
- Multi-line hunks are brittle to even minor indentation changes.
Quick repro
- Open a Go file and enable format-on-save.
- Trigger an Update that quotes a multi-line block.
- Save the file or let the formatter run before the update applies.
- Observe the error: literal string no longer matches on disk.
Fixes and workarounds
1Refresh file content
Re-read from disk immediately before constructing search strings; never assume editor buffer is canonical.
2Stabilize formatting
Temporarily disable format-on-save and auto-fixers while applying updates, then re-enable.
3Reduce hunk size
Prefer smaller, localized edits over multi-hundred-line replacements to minimize brittleness.
4Adopt semantic apply
Use an API that merges by intent, not literal strings, to avoid this class of errors entirely.
A reliable alternative: Morph Fast Apply
Morph applies updates by understanding code intent and structure, avoiding brittle string matching. Throughput is 4500+ tokens/sec with ~98% structural accuracy on first pass.
Choose the right path: If you're building your own application, integrate with Morph's OpenAI-compatible API. If you're using Claude Code, connect via our MCP server at morphllm.com/mcp.
Apply semantic edit with Morph
curl -X POST https://api.morphllm.com/v1/chat/completions \
+ -H "Authorization: Bearer YOUR_API_KEY" \
+ -H "Content-Type: application/json" \
+ -d '{
"model": "morph-v3-large",
"messages": [{
"role": "user",
"content": "<instruction>Make handleSubmit async and await calls</instruction>\n<code>...full file content...</code>\n<update>async handleSubmit; await validate and submit</update>"
}]
}'
Stop fighting brittle search-replace
Drop-in, OpenAI-compatible API. Keep your LLM, fix your apply.
FAQ
Is this a Claude Code bug?
The behavior matches limitations of literal search-replace under formatting and concurrency. See GitHub issue #968.
Will regex help?
Regex can reduce brittleness but still fails on structural edits. Semantic apply is more reliable for multi-line changes.
Advanced
To help the model see post-apply changes, include a unified diff in your prompt alongside the final code.