[BUG] Session file corrupted by truncated surrogate pair in persisted tool output preview

Resolved 💬 2 comments Opened Apr 17, 2026 by oleksii-b-username Closed May 25, 2026

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

  1. Run a Bash command whose output is >2KB and contains emoji.
  2. The 2KB preview is written into the session .jsonl as a <persisted-output> block.
  3. If the 2KB cutoff falls inside a \uD83D\uXXXX pair, only \uD83D survives.
  4. 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_

View original on GitHub ↗

This issue has 2 comments on GitHub. Read the full discussion on GitHub ↗