anthropics / anthropics/claude-agent-sdk-typescript
SDK writes illegal entries to session JSONL transcripts (empty text blocks + orphaned tool_results)
- Lenguaje dominante
- Shell
- Estrellas
- 1.8k
- Forks
- 226
- Métricas de merge de PR
- Sin PR fusionados en 30 d
Descripción
## Description
The Claude Agent SDK writes entries to session JSONL transcript files that are later rejected by the Claude API when the session is resumed. This forces SDK consumers to implement their own transcript sanitization as a workaround.
Two categories of illegal entries have been identified:
### 1. Empty text blocks in assistant messages
The SDK writes assistant messages containing `{type: "text", text: ""}` blocks to the transcript during streaming. When the session is later resumed (or compacted), the API rejects these with:
```
text content blocks must be non-empty
```
**Root cause:** During streaming, the model can produce empty text blocks (e.g., between tool calls or thinking blocks). The SDK appends these to the JSONL transcript as-is, without filtering out empty content blocks. However, the API validates that all text blocks are non-empty when they appear in the input message history on a subsequent resume/compact request.
### 2. Orphaned tool_result blocks after compaction
After context compaction, the transcript can contain user messages with `tool_result` blocks whose `tool_use_id` references a `tool_use` in an assistant message that was removed during compaction. When the session is resumed, the API rejects these with:
```
unexpected tool_use_id
```
**Root cause:** The `/compact` operation truncates older messages from the transcript. If an assistant message containing a `tool_use` block is removed but the subsequent user message containing the corresponding `tool_result` block is kept, the `tool_result` becomes orphaned — it references a `tool_use_id` that no longer exists in the conversation history. The API then rejects the transcript because every `tool_result` must reference an existing `tool_use`.
## Impact
Both issues cause 400 validation errors from the Claude API, which:
- Interrupt ongoing agent sessions
- Waste API calls (the request is rejected before any processing)
- Require consumers to implement custom transcript repair logic
- Can cascade into consecutive error loops if not handled
These errors are particularly impactful for long-running agent sessions that rely on compaction and session resumption to operate within context limits.
## Expected Behavior
1. **Empty text blocks:** The SDK should filter out empty text content blocks (`{type: "text", text: ""}`) before writing assistant messages to the JSONL transcript, or at minimum before constructing the message history for a resume/compact API call.
2. **Orphaned tool_results:** The compaction logic should ensure referential integrity — if a `tool_use` block is removed from the transcript, the corresponding `tool_result` block should also be removed (or the boundary should be adjusted to keep both).
## Workaround
We currently sanitize transcripts before every API call and reactively on 400 errors by:
1. Scanning assistant messages for empty text blocks and removing them (dropping the entire JSONL line if all content blocks are empty)
2. Collecting all `tool_use` IDs from assistant messages, then dropping user message lines that contain `tool_result` blocks referencing IDs not in that set
This works but is fragile and adds latency to every wake cycle.
## Environment
- SDK version: `@anthropic-ai/claude-agent-sdk` v0.2.63
- Node.js: v24.12+
- Provider: AWS Bedrock (Claude Opus 4.6)
- Usage pattern: Long-running agent with periodic compaction and session resumption
## Additional Error Patterns
The following API error messages indicate transcript corruption:
```
text content blocks must be non-empty
thinking blocks cannot be modified
redacted_thinking blocks cannot be modified
unexpected tool_use_id
```
The first and last are the most frequently encountered in production.
Guía de contribución
No hay ninguna guía de contribución indexada para este repositorio
Evaluación
Este issue todavía no se ha evaluado.