[BUG] Session file corrupted by truncated surrogate pair in persisted tool output preview
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?
Summary
When a Bash tool result is large (>2KB), Claude Code saves it to a .txt file
and inserts a 2KB preview into the session .jsonl. If the output contains emoji
encoded as UTF-16 surrogate pairs (e.g. \uD83D\uDE00), the truncation can split
a pair in half — leaving a lone high surrogate (\uD83D) with no low surrogate.
This produces invalid JSON. The Anthropic API rejects every subsequent turn with:
400 {"type":"error","error":{"type":"invalid_request_error",
"message":"The request body is not valid JSON: no low surrogate in string: ..."}}
The session is then permanently broken.
Steps to reproduce
- Run a Bash command whose output is >2KB and contains emoji.
- The 2KB preview is written into the session .jsonl as a <persisted-output> block.
- If the 2KB cutoff falls inside a \uD83D\uXXXX pair, only \uD83D survives.
- On the next turn the client sends the full history and receives a 400.
Concrete example
File: chat/server/src/data/emojis.json (~64.8 KB).
Grep output was truncated mid-emoji:
"🧑\uD83D ← lone high surrogate, pair partner cut off
Session file line 30485, tool: Bash (grep across src/).
Expected behavior
Preview truncation should be surrogate-aware: cut before the surrogate pair
starts, or replace incomplete pairs with U+FFFD before writing to .jsonl.
Environment
- Claude Code: 2.1.92
- OS: macOS 26.4.1 (Build 25E253)
- Shell: zsh
Workaround
import re, shutil
path = "~/.claude/projects/.../session.jsonl"
shutil.copy2(path, path + ".bak")
with open(path) as f: lines = f.readlines()
lines[N] = re.sub(r'\\u[dD][89aAbBcCdDeEfF][0-9a-fA-F]{2}', '', lines[N])
with open(path, "w") as f: f.writelines(lines)
What Should Happen?
fix this
Error Messages/Logs
Steps to Reproduce
read main desc
Claude Model
None
Is this a regression?
Yes, this worked in a previous version
Last Working Version
_No response_
Claude Code Version
in main desc
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
_No response_
This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗