[BUG] Edit tool converts hard tab characters to spaces in old_string matching, breaking edits on tab-indented files
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
The Edit tool's old_string parameter silently normalizes hard tab characters (0x09) to spaces before matching against file content. This causes every edit attempt to fail on files that use tab indentation, because the search string no longer matches the actual file content.
Claude Code itself confirms this is happening:
"The Edit tool is converting my tabs to spaces in the old_string match."
"The Edit tool is normalizing tabs. Let me use python to do the replacement."
The workaround is falling back to Python/Bash str.replace() for every edit, which defeats the purpose of the edit tool and roughly doubles or triples token cost per edit.
My entire codebase (~52,000 lines of C across multiple projects) uses hard tabs as specified in CLAUDE.md. This means every single edit Claude Code attempts goes through the fail-retry-python-fallback cycle, burning tokens on each attempt.
What Should Happen?
The edit tool should preserve all characters in old_string exactly as provided, including hard tabs.
Error Messages/Logs
Steps to Reproduce
Have Claude Code edit any file that uses hard tab indentation. The old_string match will fail because tabs are converted to spaces internally. Claude Code will then report the tool is "normalizing tabs" and fall back to alternative methods.
Claude Model
Opus
Is this a regression?
Yes, this worked in a previous version
Last Working Version
2.1.81
Claude Code Version
2.1.86 (Claude Code)
Platform
Anthropic API
Operating System
Other Linux
Terminal/Shell
VS Code integrated terminal
Additional Information
_No response_
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗