Claude Code's Edit Tool Has a Tabs Problem

· 2 min read ·
·
Claude Code CLI Debugging

Today I finally understood why Claude Code’s Edit tool was failing repeatedly on my codebase. The culprit? Tabs.

I was watching Claude attempt a simple edit. It read the file, understood the code, generated the right change. Then: Error editing file. It tried again. Same error. Read the file again. Tried a third time. Failed again.

Four attempts. Same edit. Same failure. I could almost feel it getting frustrated.

The Root Cause

Claude Code’s Edit tool uses exact string matching. The old_string parameter must match the file content byte-for-byte, including every whitespace character.

Here’s the problem: when Claude reads a file, tabs render as spaces in its view. So when it constructs the old_string for the edit, it writes spaces. But the file contains tabs. The match fails silently.

What Claude sees:     "        return <Layout"  (8 spaces)
What the file has:    "\t\treturn <Layout"      (2 tabs)
Result:               No match. Edit fails.

This gets worse with deep nesting. At 7-8 levels of indentation, counting the exact number of tabs from a rendered view is nearly impossible.

Three Whitespace Traps

TrapWhat HappensHow to Spot It
Tabs rendered as spacesClaude writes spaces, file has tabsCheck indentStyle in formatter config
Wrong indentation depth7 tabs vs 8 tabs in deeply nested codeRead a narrow line range before editing
Trailing whitespaceInvisible spaces at line endingsRun cat -et to see $ at line ends

The Fix

The moment I asked Claude to investigate, it ran a check against the formatter config. Biome was configured with "indentStyle": "tab". Every file used tabs consistently. Nothing was broken in the codebase.

The fix was on Claude’s side. It saved a persistent memory note: “This project uses tab indentation. Always use tab characters in edits.”

That’s it. One memory note. The problem disappeared for future sessions.

What I Learned

  • Claude Code’s Edit tool does byte-for-byte string matching. Whitespace must be exact.
  • Tabs render as spaces in Claude’s file view, which is the single biggest source of edit failures
  • On macOS, cat -et shows literal ^I for tabs and $ for line endings (cat -A is a Linux-only flag)
  • Claude Code’s memory system (~/.claude/ directory) can store project-specific notes that persist across sessions
  • A single memory note about indentation style eliminates an entire class of repeated failures

Running into weird Claude Code edit failures? I’d love to hear what workarounds you’ve found. Reach out on LinkedIn.