Back to home

Fix: "Error: String to replace not found in file." (Claude Code Update)

Why Claude Code's Update tool throws 'String to replace not found in file' and how to fix it reliably. Root causes, repro, and production-ready alternatives.

Morph Engineering Team

Posted by Morph Engineering Team

1 minute read


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.

100%
Reported failure rate (user)
> 1K
Lines often affected
0
AST awareness in search-replace

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

  1. Open a Go file and enable format-on-save.
  2. Trigger an Update that quotes a multi-line block.
  3. Save the file or let the formatter run before the update applies.
  4. 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.