[BUG] Claude Code does not respect file encoding, corrupts Windows-1252 files

Open 💬 23 comments Opened Sep 4, 2025 by edlyra

Environment

  • Platform (select one):
  • [ X] Anthropic API
  • [ ] AWS Bedrock
  • [ ] Google Vertex AI
  • [ ] Other: <!-- specify -->
  • Claude CLI version: 1.0.103 (Claude Code)
  • Operating System: Windows 11
  • Terminal: VSCode

Bug Description

Claude Code does not respect the original file encoding when editing files. It assumes UTF-8 encoding for all operations, which causes character corruption when working with files encoded in other formats like Windows-1252.

Steps to Reproduce

  1. Open a file that is encoded in Windows-1252 (common for Delphi/Pascal projects)
  2. Use Claude Code's Edit tool to modify text containing accented characters (e.g., Portuguese: configuração, não)
  3. The file becomes corrupted with characters like configuração instead of configuração

Expected Behavior

Claude Code should:

  • Detect the original file encoding
  • Preserve the same encoding when making edits
  • Or provide a way to configure the target encoding for edits

Current Workaround

Users must either:

  1. Accept corrupted characters and manually fix them
  2. Maintain separate UTF-8 clones of their repositories specifically for Claude Code usage
  3. Use pre-commit scripts to convert between encodings

Impact

This affects any codebase that uses non-UTF-8 encoding, particularly:

  • Legacy Delphi/Pascal projects (Windows-1252)
  • Projects with specific encoding requirements
  • International projects with accented characters

Technical Details

  • Claude Code's Read tool correctly displays Windows-1252 files
  • The Edit/Write tools force UTF-8 output regardless of input encoding
  • VSCode correctly shows Windows-1252 files when configured properly
  • The issue only occurs when Claude Code modifies the files

Environment

  • Claude Code version: [current version]
  • File encoding: Windows-1252 (ANSI - Latin 1)
  • IDE: Delphi XE
  • Language: Portuguese (Brazilian) with accented characters

This is a critical issue for maintaining legacy codebases that require specific encodings for compiler compatibility.

View original on GitHub ↗

23 Comments

github-actions[bot] · 10 months ago

Found 3 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/3416
  2. https://github.com/anthropics/claude-code/issues/5518
  3. https://github.com/anthropics/claude-code/issues/6485

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

corneliusroemer · 10 months ago

Please give your issue a descriptive title

edlyra · 9 months ago

fixing the errors generated by this issue consumes a lot of tokens

ohuet · 9 months ago

2 workarounds are on this older ticket : https://github.com/anthropics/claude-code/issues/3416

The best is probably to use this : https://github.com/devslimbr/cc-tools

github-actions[bot] · 7 months ago

This issue has been inactive for 30 days. If the issue is still occurring, please comment to let us know. Otherwise, this issue will be automatically closed in 30 days for housekeeping purposes.

VoronkovIvan · 7 months ago

Still an issue. Same with Win-1251 encoding

xrchz · 6 months ago

Still actively affecting users. This issue is part of a larger UTF-8/encoding bug pattern in Claude Code's Edit/Write tools.

I've posted a consolidated impact analysis at #13939 documenting 6+ related issues spanning 6+ months. This is a systemic problem affecting all international users.

Cross-linking for visibility: #13939, #13080, #7332, #7335

---
🤖 Generated with Claude Code

dimitar-grigorov · 5 months ago

If anyone needs a workaround today I wrote an MCP server that handles encoding-aware file reads and writes CP1251, CP1252, ISO-8859, KOI8 with auto-detection. Single Go binary, no runtime dependencies.
https://github.com/dimitar-grigorov/mcp-file-tools

EvandroLucas · 4 months ago

Still an issue, changing from windows-1252 to UTF-8 even when explicitly told not to do so.

Johen8 · 4 months ago

How come this is still a problem? Correct file encoding handling is a basic feature. Has there been any official comment from Anthropic on this besides this comment: https://github.com/anthropics/claude-code/issues/13939#issuecomment-3863005735

alex-larkin · 3 months ago

This is also affecting me in my VBA work with Spanish, as well as in Quechua languages. I'm using Claude through VSC. Every time it touches my code, the whole file comes back garbled.

WellingtonTorres · 3 months ago

The problem remains, I'm facing changing from windows-1252 to UTF-8.

omarqui · 3 months ago

Just adding here another "me too"

pvlmika · 3 months ago

Facing the same problem, would be nice to have native solution.

Lion17 · 3 months ago

I'm adding my share to raise the issue with developers supporting legacy code in C++ Builder 6.

ymonster · 3 months ago

I think we all agree that both the encoding and the line endings should just be preserved as-is.

Why a hook : hooks intercept the native Read/Edit/Write, so Claude doesn't need to remember to use a special tool. The file just stops getting corrupted, transparently.

Design goal : keep the file as-is.

  • Character sets: tested with Windows-1252, GBK, GB18030, Big5, Shift_JIS, EUC-JP, EUC-KR, ISO-8859-1. Other single-byte encodings in the same family (Vietnamese CP1258, Cyrillic CP1251, Thai CP874, etc.) aren't in my test matrix yet, but the plugin just round-trips whatever chardet detects — they should work. Reports welcome.
  • Line endings: CRLF / LF / mixed, preserved as detected.
  • Binary safety: binaryornot pre-check so binary files aren't misidentified as text.

If you need read/write encoding mapping rather than strict round-trip (e.g. read GB2312 → write GBK, or ISO-8859-1 → Windows-1252), feel free to open an issue and I'll look into it.

Install:

/plugin marketplace add ymonster/claude_encoding_guard
/plugin install encoding-guard

Repo: https://github.com/ymonster/claude_encoding_guard

lbresler · 2 months ago

Been using @ymonster's encoding-guard plugin and it solves this cleanly, hooks intercept Read/Edit/Write, chardet detects the original encoding, and the file is round-tripped back to its original encoding + line endings transparently. No more mojibake on Windows-1252 / ISO-8859-1 files.

https://github.com/ymonster/claude_encoding_guard

/plugin marketplace add ymonster/claude_encoding_guard
/plugin install encoding-guard

Until Anthropic ships a native fix, this is the most reliable workaround I've found.

Coamithra · 1 month ago

Claude says:

Still reproduces on current Claude Code (CLI as of mid-2026) on Windows 11.

Worth flagging that on Windows this is really two stacked bugs that compound:

  1. This issue — Edit/Write force UTF-8 regardless of the file's real encoding, so cp1252 / Latin-1 files get corrupted (accented chars → mojibake).
  2. **A separate, cross-platform Unicode normalization bug** in the model→tool path: an old_string containing (U+2192), (U+2014), (U+2019), / (U+201C/U+201D) or U+00A0 gets normalized/conflated before matching, so the edit either fails with "String to replace not found in file." or silently swaps the glyph. Tracked separately in #15920, #38765, #52813, #26141 — all currently closed as not-planned / stale.

On a cp1252 Windows file that also contains an em dash you hit both at once: the matcher can't locate the line, and when it does, the write corrupts the rest of the file's accented bytes.

Minimal repro for the normalization half (reproduces on any OS):

  • file contains the bytes for a — b (the is U+2014)
  • call Edit with old_string: "a — b"
  • result: 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.)

A single fix would resolve the whole cluster: treat old_string as an opaque byte sequence for matching, and preserve the file's detected encoding on write (or expose an --encoding override / preserveUnicode opt-out, applying any "helpful" normalization only as a fallback after a literal match fails, and surfacing which form matched).

Until then the only reliable workaround is shelling out to Python with an explicit encoding= and feeding the codepoints as ASCII \uXXXX escapes so the corrupting path is bypassed entirely.

mloeffler123 · 1 month ago

Facing the same problem, would be nice to have native solution.

myonlylonely · 21 days ago

AI nowadays could do anything, but they can't solve this single issue.

mloeffler123 · 20 days ago

Facing the same problem, would be nice to have native solution.

havmar · 7 days ago

Adding another data point:

Environment: Claude Code via AWS Bedrock

Codebase: Legacy PL/I mainframe sources stored in Latin-1 / ISO-8859-1 (not UTF-8). The encoding is mandated by the toolchain and can't be changed.

Symptoms (same mechanism described above):

  • Read decodes the file as UTF-8, so umlauts (ä ö ü ß) come back as the U+FFFD replacement character �.
  • Edit writes the file back as UTF-8, re-encoding every pre-existing umlaut. Lines I never touched show up as changes, flooding git diff with false encoding noise, and the result is invalid for a toolchain that requires Latin-1.

Current workaround — bypassing Read/Edit with a Python shim

viaregio · 7 days ago

Confirming this on a legacy Delphi (Windows-1252/ANSI) codebase, with a minimal, deterministic reproduction that isolates the tool from any editor.

Key finding: an ASCII-only edit — a change that touches no non-ASCII characters — still corrupts every non-ASCII byte in the whole file. So this isn't about the edited span; the tool round-trips the entire file through a lossy UTF-8 decode/encode.

Minimal reproduction

  1. Create a 3-line file encoded as Windows-1252 containing 7 non-ASCII bytes on line 2:

``powershell
$enc = [System.Text.Encoding]::GetEncoding(1252)
$ae=[char]0xE4;$oe=[char]0xF6;$ue=[char]0xFC;$ss=[char]0xDF;$Ae=[char]0xC4;$Oe=[char]0xD6;$Ue=[char]0xDC
$txt = "line 1: ASCII marker MARKER_A
rn// umlauts: $ae $oe $ue $ss $Ae $Oe $Uernline 3: ASCII endrn"
[System.IO.File]::WriteAllText("repro.txt", $txt, $enc)
# -> 7 valid cp1252 bytes (E4 F6 FC DF C4 D6 DC), 0x EF BF BD sequences, 80 bytes
``

  1. Use the Read tool on repro.txt. It displays the 7 umlauts as the replacement character (U+FFFD) — i.e. the original bytes are already lost at read time.
  1. Use the Edit tool to change only ASCII on line 1: MARKER_AMARKER_B (line 2 is untouched).
  1. Inspect the bytes:

``powershell
$b=[System.IO.File]::ReadAllBytes("repro.txt")
($b | Where-Object { $_ -in 0xE4,0xF6,0xFC,0xC4,0xD6,0xDC,0xDF }).Count # valid cp1252 umlauts
$c=0; for($i=0;$i -lt $b.Length-2;$i++){ if($b[$i]-eq0xEF -and $b[$i+1]-eq0xBF -and $b[$i+2]-eq0xBD){$c++} }; $c # EF BF BD sequences
``

Result

| | valid cp1252 umlaut bytes | EF BF BD sequences | size |
|---|---|---|---|
| before edit | 7 | 0 | 80 |
| after ASCII-only edit | 0 | 7 | 94 |

Every umlaut (E4, F6, …) became EF BF BD (the 3-byte UTF-8 encoding of U+FFFD), and the file grew by 14 bytes (7 × 2). In a Windows-1252 editor these now show as �.

Why this is bad

  • The corruption is silent and irreversible: because Read already decodes to U+FFFD, the identity of each character (ä vs ö vs ü vs ß …) is gone — it can't be recovered without re-typing from context.
  • It corrupts the entire file on any edit, so a single unrelated change to a large source file destroys hundreds of characters at once.
  • It breaks compiler-relevant strings and comments in Delphi/Pascal, C/C++, etc. that must stay in Windows-1252/ANSI.

Note re: editors

The Zed editor itself recently added legacy-encoding open/save with auto-detection (zed-industries/zed PR #44819, merged 2025-12), and it preserves Windows-1252 on save. But the agent Edit/Write tools still corrupt the file (reproduced above), which suggests they write directly rather than through the encoding-aware path.

Suggested fix

Detect the file's encoding on read and preserve it on write; or, at minimum, don't re-encode bytes that weren't part of the edit. A per-file/target-encoding override would also work.

Environment

  • OS: Windows 10 (Pro 22H2)
  • Agent: Claude Code (CLI) 2.1.193, accessed via Zed 1.10.0
  • File encoding: Windows-1252 (Delphi/Pascal codebase)