Edit tool fails to match strings in tab-indented files

Resolved 💬 3 comments Opened Mar 22, 2026 by weezy20 Closed Mar 22, 2026

Problem

When working with files that use tabs for indentation, the Edit tool's old_string parameter frequently fails to find matches, even when the string appears to be correct based on Read output. This forces falling back to Python/Bash for file edits, which defeats the purpose of the dedicated Edit tool.

Reproduction

A file using tab indentation (verified with cat -A showing ^I characters):

^I^I^I<PageTransition>$
^I^I^I^I<div$
^I^I^I^I^Iaria-live="polite"$

The Read tool displays this as:

   248→			<PageTransition>
   249→				<div
   250→					aria-live="polite"

I then attempted an Edit call with old_string containing the text as shown in the Read output (a multi-line block spanning ~50 lines). The edit failed:

String to replace not found in file.

I verified the content existed using a Python script (if old in content: print("FOUND")FOUND), confirmed the exact tab characters with cat -A, and successfully performed the replacement via Python.

What I observed

  • First Edit attempt: Failed on a ~50-line old_string that included tab-indented JSX with inline template literals and ternary expressions
  • Second Edit attempt (smaller match): Also failed on the same file with a different ~50-line block
  • Third Edit attempt (after Python fix): Succeeded on a ~40-line block in the same file with the same indentation style

The inconsistency suggests the failure isn't purely about tabs vs spaces, but may involve specific character sequences within tab-indented content that cause matching to break.

Diagnostic details

  • Platform: Linux (Ubuntu-based)
  • Model: claude-sonnet-4-6
  • File type: .tsx (React/TypeScript)
  • Indentation: Tabs (enforced by Biome formatter)
  • Indentation depth: 3–5 levels deep (3–5 tab characters)
  • Content characteristics: The failing blocks contained JS template literals with ${} interpolation, ternary chains, and inline style objects — all tab-indented

Why I think this happens

The Read tool output format uses cat -n style: 251→<tab>content. The arrow + tab separator is ambiguous when the file content itself begins with tabs. When constructing old_string from Read output, it's easy to get the tab count wrong by ±1 because one tab is consumed by the line-number formatting. The larger the block being matched, the more likely at least one line has a whitespace mismatch.

Suggestions

  • Whitespace-tolerant matching mode: An optional flag on Edit that normalizes leading whitespace (tabs↔spaces) during comparison
  • Clearer Read output: Use a non-whitespace separator between line numbers and content (e.g., 251| content with a pipe instead of tab) so tab-indented content is unambiguous
  • Better error diagnostics: When old_string fails to match, show the closest near-match with a diff highlighting where the mismatch occurred (e.g., "Line 5: expected 4 tabs, found 3")

View original on GitHub ↗

This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗