Claude Code 的 Edit 工具为何因制表符反复编辑失败
Original title: TIL: Claude Code's Edit Tool Has a Tabs Problem
The title and summary in the selected language are awaiting translation.
作者发现 Claude Code 的 Edit 工具反复报错的原因是制表符问题:该工具用 old_string 做逐字节精确匹配,但读取文件时制表符在它的视图里渲染成空格,于是它写出空格去匹配文件里的制表符,匹配静默失败。
March 16, 2026 2 min read
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
| Trap | What Happens | How to Spot It |
|---|---|---|
| Tabs rendered as spaces | Claude writes spaces, file has tabs | Check indentStyle in formatter config |
| Wrong indentation depth | 7 tabs vs 8 tabs in deeply nested code | Read a narrow line range before editing |
| Trailing whitespace | Invisible spaces at line endings | Run 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 -etshows literal^Ifor tabs and$for line endings (cat -Ais 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
Source: Kondasamy Jayaraman · Engineering Blog · kondasamy.com