claude-code - 💡(How to fix) Fix Edit tool silently normalizes `\uXXXX` escape sequences in old_string, breaking exact matches [2 comments, 3 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
anthropics/claude-code#52813Fetched 2026-04-25 06:20:14
View on GitHub
Comments
2
Participants
3
Timeline
6
Reactions
0
Author
Timeline (top)
labeled ×4commented ×2

The Edit tool appears to transparently convert between \uXXXX escape sequences and their literal Unicode codepoints when matching old_string against file contents. When the target file legitimately contains the six ASCII characters \, u, 0, 0, A, 0 (e.g., inside a JS/TS regex), no form of old_string matches — and there's no way to opt out.

Error Message

  1. Error returned: The error message confirms the harness tried both the escape form and the literal-NBSP form — neither matched, because the input was presumably rewritten to the NBSP form before comparison while the file contains the ASCII-escape form.

Root Cause

The error message confirms the harness tried both the escape form and the literal-NBSP form — neither matched, because the input was presumably rewritten to the NBSP form before comparison while the file contains the ASCII-escape form.

Fix Action

Fix / Workaround

Something in the input-processing path rewrites   (and presumably any \uXXXX) to the actual codepoint before comparison, making it impossible to match source code that contains the escape sequence as literal text. Workaround required shelling out to python3 / sed, or git checkout <path> when the edit was effectively a revert of uncommitted changes.

Code Example

const key = s.replace(/\u00A0/g, ' ');

---

String to replace not found in file.
   (note: Edit also tried swapping \uXXXX escapes and their characters;
    neither form matched, so the mismatch is likely elsewhere in old_string.)
RAW_BUFFERClick to expand / collapse

Summary

The Edit tool appears to transparently convert between \uXXXX escape sequences and their literal Unicode codepoints when matching old_string against file contents. When the target file legitimately contains the six ASCII characters \, u, 0, 0, A, 0 (e.g., inside a JS/TS regex), no form of old_string matches — and there's no way to opt out.

Steps to reproduce

  1. Create a file repro.ts containing:

    const key = s.replace(/\u00A0/g, ' ');

    Verify the file literally contains backslash-u-0-0-A-0 via od -c repro.ts — six ASCII chars, not an NBSP codepoint.

  2. Invoke Edit with old_string equal to that same line (same six ASCII chars).

  3. Error returned:

    String to replace not found in file.
    (note: Edit also tried swapping \uXXXX escapes and their characters;
     neither form matched, so the mismatch is likely elsewhere in old_string.)

    The error message confirms the harness tried both the escape form and the literal-NBSP form — neither matched, because the input was presumably rewritten to the NBSP form before comparison while the file contains the ASCII-escape form.

Expected

old_string is matched as a raw byte sequence. If the caller passes six ASCII chars, the tool looks for six ASCII chars.

Actual

Something in the input-processing path rewrites   (and presumably any \uXXXX) to the actual codepoint before comparison, making it impossible to match source code that contains the escape sequence as literal text. Workaround required shelling out to python3 / sed, or git checkout <path> when the edit was effectively a revert of uncommitted changes.

Impact

Common in real codebases — any regex over NBSP / ZWSP / control chars, unicode-escape tests, tokenizer fixtures, JSON-encoded strings in source. Rare enough to not bite often, painful and opaque when it does.

Suggested fix

Treat old_string as an opaque byte sequence. If "helpful" normalization is desired as a fallback, only apply it when the literal match fails, and surface which form matched so the caller understands what happened.

Environment

  • Claude Code CLI - 2.1.119 (Claude Code)
  • Platform: Linux
  • Model: Opus 4.7

Related

  • #50483 — Read tool rendering \uXXXX inconsistently on Windows. Adjacent symptom (Edit failures after Read) but different root cause: in this report, the file bytes were verified via od -c before the Edit call, so Read was not misleading — the normalization is happening on Edit's old_string input itself.

extent analysis

TL;DR

Treat old_string as an opaque byte sequence to prevent unwanted normalization of Unicode escape sequences.

Guidance

  • Verify that the issue is indeed caused by the normalization of Unicode escape sequences by checking the file contents with od -c and comparing it to the old_string input.
  • Consider using a workaround such as shelling out to python3 or sed to perform the replacement, as mentioned in the issue.
  • If possible, modify the Edit tool to treat old_string as an opaque byte sequence, or apply normalization only as a fallback when the literal match fails.
  • Test the fix with different inputs, including Unicode escape sequences and literal characters, to ensure that the issue is fully resolved.

Example

No code snippet is provided as the issue is more related to the behavior of the Edit tool rather than a specific code snippet.

Notes

The issue seems to be specific to the Edit tool in the Claude Code CLI, and the suggested fix is to treat old_string as an opaque byte sequence. However, without more information about the internal workings of the Edit tool, it's difficult to provide a more detailed solution.

Recommendation

Apply workaround: Use a workaround such as shelling out to python3 or sed to perform the replacement, as the root cause of the issue is the unwanted normalization of Unicode escape sequences in the Edit tool.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

claude-code - 💡(How to fix) Fix Edit tool silently normalizes `\uXXXX` escape sequences in old_string, breaking exact matches [2 comments, 3 participants]