[BUG] German umlauts (ä, ö, ü) randomly replaced with ASCII substitutes (ae, oe, ue)

Open 💬 39 comments Opened Dec 16, 2025 by HookHM
💡 Likely answer: A maintainer (blois, collaborator) responded on this thread — see the highlighted reply below.

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?

When communicating in German, Claude Code inconsistently replaces German umlauts and special characters with their ASCII equivalents:

  • ä → ae
  • ö → oe
  • ü → ue
  • ß → ss

Examples:

  • "für" written as "fuer"
  • "können" written as "koennen"
  • "löschen" written as "loeschen"

Expected behavior:
Claude should consistently use proper Unicode umlauts (ä, ö, ü, ß) when writing in German.

Actual behavior:
Umlauts are randomly replaced with ASCII substitutes. This happens inconsistently - sometimes within the same response, some words have correct umlauts while others use substitutes.

Reproducibility:
Occurs frequently but inconsistently. No clear pattern identified for when umlauts are preserved vs. substituted.

Impact:

  • Unprofessional appearance in documentation and code comments
  • Inconsistent codebase when Claude generates German text
  • Particularly problematic with proper names (e.g., author names in file headers)

Environment:

  • Claude Code CLI v2.0.70 (Opus 4.5 · Claude Max)
  • macOS 26.2
  • Terminal: default macOS Terminal / iTerm2
  • German language project with German documentation

Current workaround:
Manual correction of all German text output.

This is a recent regression - started ~2-3 weeks ago. Umlauts worked perfectly before.

What Should Happen?

Claude should consistently use proper Unicode umlauts (ä, ö, ü, ß) when writing in German text, including:

  • Chat responses
  • Code comments
  • Documentation
  • Proper nouns and names (e.g., "Müller" not "Mueller")

Error Messages/Logs

Steps to Reproduce

  1. Start a Claude Code session
  2. Write in German (e.g., "Erkläre mir diese Funktion")
  3. Observe response - umlauts randomly replaced with ASCII (ä→ae, ö→oe, ü→ue, ß→ss)

Claude Model

Opus

Is this a regression?

Yes, this worked in a previous version

Last Working Version

_No response_

Claude Code Version

v2.0.70

Platform

Anthropic API

Operating System

macOS

Terminal/Shell

Terminal.app (macOS)

Additional Information

_No response_

View original on GitHub ↗

39 Comments

github-actions[bot] · 7 months ago

Found 2 possible duplicate issues:

  1. https://github.com/anthropics/claude-code/issues/13939
  2. https://github.com/anthropics/claude-code/issues/7335

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

HookHM · 7 months ago

Not a duplicate. Related but different issue:

  • #7335: Character corruption (→ �) when editing files on Windows
  • #13939: Turkish UTF-8 corruption when editing files
  • This issue: ASCII substitution (ä→ae) in chat responses on macOS

Different symptom (substitution vs corruption), different context (chat output vs file editing), likely different root cause.

github-actions[bot] · 6 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.

buffcode · 5 months ago

still occuring frequently

Kinzal16 · 5 months ago

Very often. The problem appeared overnight; it wasn't always there.

iBoarder · 5 months ago

Same issue here. Still happening frequently.
What’s strange: sometimes Claude doesn’t even use ASCII substitutes anymore - it just drops the umlaut entirely.
Example: “Verzogerung” instead of “Verzögerung”
This is a recent regression, started a few

AdlerCentauri · 5 months ago

The issue is getting progressively worse and should be fixed as soon as possible.​​​​​​​​​​​​​​​​

lukasfehling · 5 months ago

This is getting worse - Claude is now even replacing existing occurrences of ü, ä, and ö with ue, ae, and oe, or simply substituting them with u, a, and o. Please fix this soon!

LevelOne2k · 5 months ago

The issue is getting worse by the day. New symptoms:

1. Umlauts completely dropped (not even ASCII substitutes):

  • "uber" instead of "über"
  • "anderung" instead of "Änderung"
  • "Verzogerung" instead of "Verzögerung"

2. Random language mixing in the same response:

  • Starts in German: "Alle drei Findings hängen zusammen..."
  • Switches to English mid-text: "Before I make changes, I need to understand..."
  • Back to German: "Ich schaue mir zuerst das..."

Claude Code v2.1.31, Opus 4.5, macOS

gerhard-mueller · 5 months ago

Happens for me as well, I found out:

The main conversation agent uses correct Unicode, only subagents are affected

rsiuda · 5 months ago

I see this behavior constantly with German language answers using Opus. Sonnet works as expected.

  • Claude Desktop macOS, Opus 4.6 / Claude 1.1.2685 (f39a62)
  • Claude.ai, Opus 4.6
  • Claude Code v2.1.39 macOS, Opus 4.6

No matter if a simple text answer or sub-agents are used.

LevelOne2k · 5 months ago

This problem is so annoying.

HookHM · 5 months ago

Beyond the visual and linguistic issues, ASCII replacements also waste tokens unnecessarily. Each replacement adds an extra character:

"ä" → "ae" (1 char → 2 chars)
"ö" → "oe" (1 char → 2 chars)
"ü" → "ue" (1 char → 2 chars)
"ß" → "ss" (1 char → 2 chars)

In a typical German response, this can add up to dozens of extra characters, resulting in higher token usage for both input and output. This affects not only file writes but also chat responses, where hooks cannot intervene.

AdlerCentauri · 4 months ago

The issue is getting worse by the day. New symptoms:

1. Umlauts completely dropped (not even ASCII substitutes):

  • "Losungsvorschlage" instead of "Lösungsvorschläge" (two umlauts missing in one word)
  • "mochtest" instead of "möchtest"
  • "fur" instead of "für"
  • "uber" instead of "über"
  • "anderung" instead of "Änderung"

2. Random language mixing in the same response:

  • Starts in German: "Alle drei Findings hängen zusammen..."
  • Switches to English mid-text: "Before I make changes, I need to understand..."
  • Back to German: "Ich schaue mir zuerst das..."

This is becoming unusable for German-speaking users.

Claude Code v2.1.50, Opus 4.6, macOS

Jur92 · 4 months ago

This issue is getting progressively worse day by day. When will someone from Anthropic finally address and fix this extremely annoying and frustrating bug?

TheRealTremes · 4 months ago

This problem is absolutely unacceptable and Claude Code has become almost unusable because of it. It is getting worse every day — even when explicitly telling Claude Code to use umlauts, it only works for about 2 minutes before reverting back to ASCII substitutes. This must be fixed immediately.

NubeBuster · 3 months ago
● You're right, I was wrong — the file already exists without !. And the path is /home/mark/storagevids/ not /home/mark/mnt/storagebox-videos/. Let me try with the correct path:

● Bash(exiftool "/home/mark/storagevids/dlgui_downloads/Filename with I'M char as welll as perfectly legal !.mp4")                                                                                   
  ⎿  Error: Exit code 1      
     Error: File not found - ...                                                     
                                                                                                                                                                                                                                      
● Let me check what the Bash tool actually passes:                                                                                                                                                                                    
                                                                                                                                                                                                                                      
● Bash(echo -n "I'M" | xxd)                                                                                                                                                                                                           
  ⎿  00000000: 4927 4d                                  I'M                                                                                                                                                                           
                                                                                                                                                                                                                                      
● There it is. The Bash tool is converting U+2019 (e2 80 99) to ASCII ' (27) before passing it to the shell. That's the bug — Claude Code normalizes smart quotes to ASCII quotes in the command string.                              
                                                                                                                                                                                                                                      
  So there's no way to pass U+2019 through the Bash tool at all. This confirms updating sanitize_filename to strip/replace these chars is the right fix.                                                                              
                                                                                                                                                                                                                                      
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
!                                                                                                                                                                                                                                     
──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
  ! for bash mode
......................-===---------.....................
..................=----............-----................
..............=+=+-:.:.:...............----.....:::.....
............=+*--:.:.:....................---....:--....
..........:-++-.:..............:::::::::::.----=..:-::..
..........=+=.:.............::-:::::::::::.:..:==..::::.
.........-+-:.:..........::::::::::-=--::::::.+:++..::-:
........-+=-:.:..........:::........---==+=...:=+++-:.-:
........+=-.:...:.......:::::::::::..-===++*#++-+#+===.-
........=+-.:......::-::::::.:---=-==.....-==+##***=.:--
.......===.:.:...::::::---======-=+++**+*###*#+**%#%--:-
.......=+=.:.:..::::::===-..--====-===#+++=..+**=#%%#--:
.......-+-.:....::::::::---=======.===++++++##*%%#%#%#=-
.......--=.:....:::::::::::=....===-====+++:+##%%@%%@+==
.......=-=-.......:::::::.......-.-----=****=*+...#%@%==
........-=---.........=.:-..-..:....-==+###*::::...*%%++
........-----......-=====--.........--=+%#%=:....=-=#%+#
.........-==-.....-..===-----......---=+#%#*=::..:+*%%#+
.........--==.........===+==+---..:---+++%+***==-#%%@%%+
...........==..:.......===+++##***++==+++%%=####%%%@@@@=
............=-.:........==+**####*++===++#%@#-##%%%@@@%=
............-=-:::...--.-==++###*+.==+++%%%%%-##%@@%%%+#
.............=-.::....--...=+***++.=++-:*#%%+##%%%%%++#%
.............--.:::....==.-++++*+.++++++**##%##%%%%*###%
.............=-.:::::..:==.++++++++****###%%%@%%%%%+%%%#
.............=-::::.::..:==++++*-..:+***#####%%@@@####%#
.............=-..::.::--..-++++++******###%%%%@@@@%%%%%#
............==-.:::--------.=++********####%%@%%@#%%#%%%
...........-=-::::---==-=+-+=.+*+***####%%@@%%%+#%%%@@@@
...........==-::::---====++++++.+*****##%####==**##%%@@@
..........===-:::..--====++++*+++*#:::---+=++++**##%%@%@
.........===--::.:---=====+++***+*++***#-==++++*#*%#%%%@
........===--..:-:---========++++*+:*+***======++#%#%%%%
.-=========-----::------=+======+++++++**#####%%%%%%@@@%
schmik · 3 months ago

Regarding the “platform:macos” label: This happens on Windows (11) too

msouga · 3 months ago

Adding the Spanish diacritics case to reinforce this is a cross-language issue, not specific to German.

Same bug, Spanish: Claude Code consistently strips tildes (á, é, í, ó, ú), eñes (ñ), and opening punctuation (¿, ¡) when generating large text blocks in Spanish — even when CLAUDE.md explicitly mandates correct Spanish orthography. The model generates correct output on a manual retry, confirming it can do it, but defaults to ASCII-safe output on the first pass.

Filed as #26128 (closed as stale/duplicate, linked here for reference).

Observed pattern across languages:

  • Spanish: tildes and ñ stripped → "accion" instead of "acción", "diseno" instead of "diseño"
  • German (this issue): umlauts replaced → "ae/oe/ue" instead of "ä/ö/ü"
  • Root behavior is identical: non-ASCII characters in the U+00C0–U+024F range are substituted with ASCII equivalents under load (large outputs, long sessions)

Additional data point: The issue is significantly worse in long sessions. With context compression active, CLAUDE.md language instructions appear to be deprioritized, making the model revert to ASCII-safe output even mid-session after having written correctly earlier. See also #34779.

Impact: When generating documentation (~250–750 lines), the entire output has to be discarded and regenerated. For non-ASCII languages this is not a minor inconvenience — it doubles token consumption and makes Claude Code unreliable for professional writing in any language outside ASCII.

msouga · 3 months ago

Follow-up to my previous comment: adding the full cross-language map and the root cause analysis that ties all of these together.

#32886 contains a detailed investigation of cli.js that identifies three structural causes for this entire class of bugs:

  1. The language instruction template generates a vague directive ("respond in de/es/pt-BR") with no mention of orthographic correctness or character fidelity — the model treats accent-free output as acceptable
  2. The CLAUDE.md wrapper injects "this context may or may not be relevant to your tasks" — this explicitly frames language rules as optional context, which the model deprioritizes during coding tasks
  3. The context compaction function summarizes conversation history without including language/locale instructions — so every long session degrades into ASCII-safe output regardless of user configuration

All open issues caused by the same structural failure:

| Issue | Language | Symptom |
|-------|----------|---------|
| #32886 | Portuguese, French, Vietnamese, Czech, Spanish (any diacritics) | Language setting does not enforce diacritical marks |
| #14131 | German | ä/ö/ü/ß → ae/oe/ue/ss |
| #26128 | Spanish | á/é/í/ó/ú/ñ/¿/¡ stripped (closed as stale, unresolved) |
| #34779 | Spanish | CLAUDE.md language rules lost after context compaction |
| #15768 | Japanese | Panic: byte index not a char boundary |
| #14287 | Chinese | Panic: UTF-8 boundary crash (oncall) |
| #34134 | Arabic | RTL text rendered reversed |
| #17357 | Armenian | Script not generated at all |
| #34247 | CJK/Unicode | Mojibake on Windows |

The fix is documented in #32886. Three targeted changes to the language instruction template, the CLAUDE.md wrapper, and the compaction prompt. This is not a localization feature request — it is a correctness bug that makes Claude Code unreliable for the majority of users who do not write in English.

LevelOne2k · 3 months ago

@msouga Thanks for the detailed analysis. Worth noting: the bug also occurs in the Claude.ai iOS app where cli.js is not involved at all. This suggests there is an additional model-level component to this bug beyond the three structural issues in cli.js.

LevelOne2k · 3 months ago

@bcherny Is the fix you mentioned in #32886 (“Fix going out tomorrow”) also covering #14131 (German umlauts replaced with ae/oe/ue/ss)? Has this been included in v2.1.105 or is it coming in a subsequent release?

Dekadinious · 3 months ago

I want to flag this also happening with Scandinavian æ/ø/å all the time.

NubeBuster · 2 months ago

/dontclose

aparajita · 2 months ago

It's a generalized non-ASCII character bug. The Write tool refuses to even write curly quotes and apostrophes.

MaxKlaxxMiner · 1 month ago

Still an ongoing recurring problem, even though this was also explicitly stored in the memories... :(

aparajita · 1 month ago

You have to tell claude to use python to write non-ASCII characters. Here's the rule I use for curly quotes/apostrophes, just change the language to reference all non-ASCII characters.

### Writing curly quotes/apostrophes (Claude Code limitation)

The `Edit` / `Write` tools cannot emit curly characters (“ ” ‘ ’). This matters **only when the new or changed value itself contains them** — editing an ASCII-only line works normally even though the file is full of curly characters elsewhere.

When a value needs curly characters, do a *targeted* edit via `Bash` + python3 — modify only the relevant lines, do not retype the whole file:
python3 - <<'EOF'
path = 'src/main/resources/songscribe/strings.properties'
lines = open(path, encoding='utf-8').read().splitlines(keepends=True)
for i, l in enumerate(lines):
    if l.startswith('confirm.song.empty.title '):
        lines[i] = 'confirm.song.empty.title = The song must have a title. Use “Untitled” or continue editing?\n'
open(path, 'w', encoding='utf-8').write(''.join(lines))
EOF
LevelOne2k · 1 month ago

@bcherny

michelalbers · 1 month ago

+1

MaxKlaxxMiner · 1 month ago

Update: same problems with new Opus 4.8... :)

LevelOne2k · 1 month ago

Post a new reply to Boris in Threads. "His username there is @boris_cherny."

blois collaborator · 1 month ago

This is expected to occur less frequently when the language is specified in Claude Code settings. I would like to know if folks have that specified and it still repro's, or if it resolves it.

aparajita · 1 month ago
This is expected to occur less frequently when the language is specified in Claude Code settings. I would like to know if folks have that specified and it still repro's, or if it resolves it.

"less frequently"? Why should it happen at all? For any application to have trouble with non-ASCII text in 2026 is frankly astonishing.

Dekadinious · 1 month ago
This is expected to occur less frequently when the language is specified in Claude Code settings. I would like to know if folks have that specified and it still repro's, or if it resolves it.

I want Claude Code to be set to English. I mostly work in English but touch other languages occasionally.

LevelOne2k · 26 days ago

@bcherny

jibi-collab · 8 days ago

I have been fighting this issue for a long time now. I have several claude.md rules in different places (root and projects.) It is the very first rule in my profile instructions in claude and yet it still happens on a regular basis. This sucks because this leads to a higher token consumtions to have all the ouptut corrected.

LevelOne2k · 8 days ago

@jibi-collab You’re absolutely right. I have the exact same experience — multiple CLAUDE.md rules in root and project folders, plus explicit profile instructions, and it still happens constantly. And you’re spot on about the token consumption: having to correct all the output over and over wastes a significant amount of tokens.

The core problem is that this shouldn’t require any rules or one or even several .md files in the first place. A model should understand on its own that it needs to use correct umlauts when writing in German, without any workarounds. Having to constantly fight it with rules that get ignored after a few minutes anyway is not a real solution.

You should also mention @boris_cherny in a post on Threads — he responded there before and that’s been the fastest way to get attention on this bug.

@bcherny

4homeassistant · 1 day ago

SOOOO annoying! No matter where you specify the correct behaviour (org prompt, memories, harness) - the output is still totally random. Even in ONE single answer it begins with umlauts and switches to ASCII replacements. I really don't understand why this happens in an AI that targets business customers.

LevelOne2k · 1 day ago

@4homeassistant You should also mention @boris_cherny in a post on Threads — he responded there before and that’s been the fastest way to get attention on this bug.

@bcherny