Unicode/UTF-8 Character Corruption in Hook System
Claude Code Bug Report: Unicode/UTF-8 Character Corruption in Hook System
Summary
Claude Code incorrectly encodes non-ASCII characters (Turkish, Chinese, Arabic, etc.) when passing user input to hooks, causing severe character corruption that affects session logging and other hook-based functionality.
Environment
- Claude Code Version: Latest (as of August 21, 2025)
- Platform: Windows 10/11
- Language: Turkish characters tested (çÇ şŞ ğĞ üÜ ıİ öÖ)
- Hook System: user_prompt_submit.py hook receiving corrupted data
Issue Description
Expected Behavior
When a user types Turkish text like "Ağustos" (August in Turkish), hooks should receive properly encoded UTF-8 characters.
Actual Behavior
Claude Code corrupts Turkish characters by incorrectly interpreting UTF-8 bytes as individual Latin-1 characters, then JSON-escaping them.
Character Corruption Examples
| Input Character | Correct UTF-8 | Corrupted in JSON | Result After JSON Decode |
|-----------------|---------------|-------------------|-------------------------|
| ğ | \u011f | \u00c4\u0178 | Displays as "Ä" + control char |
| ş | \u015f | \u00c5\u0178 | Displays as "Å" + control char |
| ı | \u0131 | \u00c4\u00b1 | Displays as "ı" |
| ç | \u00e7 | \u00c3\u00a7 | Displays as "ç" |
| ü | \u00fc | \u00c3\u00bc | Displays as "ü" |
| ö | \u00f6 | \u00c3\u00b6 | Displays as "ö" |
Technical Analysis
Root Cause
Claude Code's input processing pipeline incorrectly:
- Takes proper UTF-8 input from user
- Misinterprets UTF-8 byte sequences as individual Latin-1 characters
- JSON-encodes these misinterpreted characters as Unicode escape sequences
- Sends corrupted data to hooks
Example Data Flow
User Input: "Türkçe" (Turkish language)
What hooks receive: "T\u00c3\u00bcrk\u00c3\u00a7e"
After JSON decode: "Türkçe" (corrupted)
Should be: "Türkçe"
Steps to Reproduce
- Set up Claude Code with hook system in a project directory
- Configure a
user_prompt_submit.pyhook to log user input to JSON - Type any message containing Turkish characters: "Merhaba dünya"
- Check the JSON log file created by the hook
- Observe corrupted Unicode escape sequences instead of proper Turkish characters
Impact
Affected Systems
- Hook-based session logging - All non-ASCII characters corrupted
- International users - Turkish, Chinese, Arabic, Russian, and other non-Latin script users affected
- Custom workflow automation - Any hook processing user text with international characters
Severity
- High - Affects all international users using hooks
- Data integrity - User input is permanently corrupted in hook-generated logs
- Accessibility - Makes Claude Code unusable for non-English workflows involving hooks
Important Note
The main Claude Code conversation transcripts (.jsonl files) store characters correctly. This bug specifically affects the hook system's data pipeline, not the core conversation storage.
Location of correct transcripts: ~/.claude/projects/[project-hash]/[session-id].jsonl
Workaround Implemented
We developed a character mapping fix that reconstructs corrupted Turkish characters:
replacements = {
'\u00c5\u0178': 'ş', # ş
'\u00c4\u0178': 'ğ', # ğ
'\u00c4\u00b1': 'ı', # ı
'\u00c3\u00a7': 'ç', # ç
'\u00c3\u00bc': 'ü', # ü
'\u00c3\u00b6': 'ö', # ö
}
However, this is a band-aid solution. The core issue needs to be fixed in Claude Code's text processing pipeline.
Recommended Fix
- Fix input encoding: Ensure user input maintains proper UTF-8 encoding throughout the pipeline
- JSON serialization: Use proper UTF-8 aware JSON serialization when sending data to hooks
- Testing: Add comprehensive Unicode tests for all hook types
- Documentation: Update hook documentation to specify UTF-8 handling
Test Cases for Validation
Turkish Characters
- Input: "Türkçe çalışma şekli için ğöz üıl"
- Expected in hooks: Exact same characters, properly encoded
Other Languages
- Chinese: "你好世界"
- Arabic: "مرحبا بالعالم"
- Russian: "Привет мир"
All should pass through to hooks without corruption.
Additional Context
This bug significantly impacts the international usability of Claude Code's hook ecosystem. Users from non-English speaking countries cannot reliably use hook-based features, which limits Claude Code's global adoption for development workflows.
The fix should be straightforward - ensuring proper UTF-8 encoding is maintained from user input through to hook delivery, rather than the current Latin-1 misinterpretation approach.
7 Comments
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.
Yes its still a problem
Bug Report: Box-Drawing Character Corruption in Markdown Output
## Summary
Claude Code occasionally outputs ASCII box-drawing diagrams that get corrupted into null byte sequences, rendering them unreadable in the final markdown file.
## Environment
## Reproduction
When Claude Code generates ASCII box diagrams (like architectural flowcharts or data structure visualizations), the box-drawing characters get replaced with null bytes and
sentinel characters.
Expected Output:
┌───────────────────────────────────────┐
│ BOOTSTRAP (runs once at startup) │
├───────────────────────────────────────┤
│ 1. Pre-parse globals → Configure svcs │
└───────────────────────────────────────┘
Actual Output (hex view):
0c 00 00 00 00 00 00 ... 10 0a
02 20 42 4f 4f 54 53 54 52 41 50 ...
1c 00 00 00 00 00 00 ... 00 24
02 20 31 2e 20 50 72 65 2d 70 61 72 73 65 ...
## Character Mapping Discovered
| Hex Bytes | Intended Character | Description |
|-----------|-------------------|-------------|
|
0x02 0x0a|│\n| Vertical line + newline ||
0x02 0x20|│| Vertical line + space ||
0x00(repeated) |─| Horizontal line (variable length) ||
0x0c 0x00 0x00|┌| Top-left corner ||
0x10 0x0a|┐\n| Top-right corner + newline ||
0x1c 0x00 0x00|├| Left T-junction ||
0x00 0x24|┤| Right T-junction (null + dollar sign) ||
0x14 0x00|└| Bottom-left corner ||
0x18 0x0a|┘\n| Bottom-right corner + newline |## Additional Issues
0x00bytes result in misaligned right edges across different boxes0x24(ASCII `/feedback Regression in plan/markdown artifact output. Recently this has been happening consistently enough that we made aquick fix script.
) appears as a sentinel marker for right-edge characters, not as an actual dollar sign
## Impact
## Workaround
Created a repair script that maps null byte patterns back to proper UTF-8 box-drawing characters with width normalization:
/scripts/workspace/fix-markdown-nulls.tsThis issue has been automatically closed due to 60 days of inactivity. If you're still experiencing this issue, please open a new issue with updated information.
This issue was closed incorrectly despite recent human comments. This behavior of the bot is reported at https://github.com/anthropics/claude-code/issues/16497. Upvote or comment on that issue, so maybe it gets noticed.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.
This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.