[BUG] Agent SDK crashes with "Unterminated string in JSON" when tool output contains U+2028/U+2029 characters
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?
[AGENT SDK BUG - not CLI]
The Agent SDK crashes with "Unterminated string in JSON" when a tool returns content containing Unicode Line Separator (U+2028) or Paragraph Separator (U+2029) characters. These characters commonly appear in web-scraped content and cause ProcessTransport.readMessages to fail when parsing JSONL from the CLI.
What Should Happen?
The SDK should properly handle U+2028 and U+2029 characters in tool outputs without crashing. These are valid Unicode characters that appear in real-world web content.
Error Messages/Logs
SyntaxError: Unterminated string in JSON at position 872 (line 1 column 873)
at JSON.parse (<anonymous>)
at ProcessTransport.readMessages (sdk.mjs:13316:32)
at async Query.readMessages (sdk.mjs:13583:24)
Steps to Reproduce
- Create a Bash skill/tool that runs:
```bash
printf '{"success": true, "data": {"markdown": "hello'
printf '\xe2\x80\xa8'
printf 'world"}}\n'
exit 0
- Agent calls this tool
- SDK crashes with: Unterminated string in JSON at position 136
Root cause: U+2028 and U+2029 act as line terminators in JavaScript. When the SDK reads JSONL line-by-line, these characters split the JSON mid-string, causing parse failure.
Workaround: Sanitize tool outputs: sed $'s/\xe2\x80\xa8//g' | sed $'s/\xe2\x80\xa9//g'
Environment:
- @anthropic-ai/claude-agent-sdk@0.1.76
- Node v24, Linux (Debian 12)
Key fixes:
- Added
bashlanguage hint to code blocks - Fixed list indentation (3 spaces for nested code block)
- Bolded section headers
- Backticks around package name
Claude Model
Not sure / Multiple models
Is this a regression?
No, this never worked
Last Working Version
_No response_
Claude Code Version
N/A - Using Agent SDK directly (@anthropic-ai/claude-agent-sdk@0.1.76), not Claude Code CLI
Platform
Anthropic API
Operating System
Ubuntu/Debian Linux
Terminal/Shell
Other
Additional Information
Why this happens in practice
U+2028 (0xE2 0x80 0xA8) and U+2029 (0xE2 0x80 0xA9) commonly appear in web-scraped content. They're invisible in most editors but act as line terminators in JavaScript, breaking JSONL line-by-line parsing.
## Technical details
The SDK's ProcessTransport reads CLI output line-by-line. When a JSON string contains U+2028/U+2029, the line gets split mid-string:
Expected: {"content": "hello\u2028world"}
Parsed as two lines:
Line 1: {"content": "hello ← Unterminated string
Line 2: world"}
## Suggested fix
Escape or strip U+2028/U+2029 when serializing tool outputs to JSONL, or use a JSON-aware line parser instead of splitting on newlines.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗