Assistant text between tool calls is silently lost: not rendered, not in Ctrl+O, not persisted to session .jsonl (interleaved thinking)

Open 💬 0 comments Opened Jul 15, 2026 by kk1987

Environment

  • Claude Code v2.1.210, CLI TUI in macOS Terminal (Darwin 25.5.0)
  • Model: claude-fable-5 (produces interleaved thinking blocks)
  • Session type: claude.ai/code-connected session; evidence below is from the local session .jsonl under ~/.claude/projects/

Summary

When the assistant emits a text block followed by tool_use blocks in the same response, and the response also contains interleaved thinking blocks, the text block is silently lost: it is (a) never rendered in the main conversation view, (b) not visible in the Ctrl+O transcript viewer, and (c) absent from the session .jsonl on disk — verified with both raw grep and JSON-decoded search (jq '[.. | strings] | join(" ")'), so it is not an encoding/escaping artifact. This is distinct from the known AskUserQuestion overlay family (#23862, #30422, #58207), which is display-layer occlusion of the last line; here the content is not persisted at all, so the user has no way to ever see it and --resume from the local file permanently drops it from context.

Worst case observed: a ~1,800-char findings message written immediately before an AskUserQuestion call was completely lost — the user answered the multiple-choice question without ever seeing the analysis it was based on, and only noticed when the assistant later referred back to "the message above the question".

Evidence (sanitized structure dump of one session)

Per-record content-block types extracted with:

jq -r 'select(.type=="assistant") | .timestamp + "  " + ([.message.content[]? | if .type=="tool_use" then "tool_use(" + .name + ")" elif .type=="text" then "text[" + (.text|length|tostring) + " chars]" else .type end] | join(", "))' session.jsonl

In a ~1h session the model emitted roughly 30 mid-turn narration text blocks (confirmed live on screen-side context; the assistant restated several of them later, and the API turn continued normally). Only 11 text records exist in the .jsonl. Every dropped text shares one structural signature — the file shows two consecutive thinking records written milliseconds apart, then the tool_use(s), with the text gone:

Dropped example 1 — the lost ~1.8k-char message directly before AskUserQuestion:

2026-07-15T00:36:58.437Z  thinking
2026-07-15T00:36:58.465Z  thinking            <- 28 ms apart
2026-07-15T00:37:06.055Z  tool_use(AskUserQuestion)

Dropped example 2 — narration before an Edit batch:

2026-07-15T00:36:01.457Z  thinking
2026-07-15T00:36:01.459Z  thinking            <- 2 ms apart
2026-07-15T00:36:05.224Z  tool_use(Edit)
2026-07-15T00:36:10.445Z  tool_use(Edit)
2026-07-15T00:36:20.440Z  tool_use(Edit)

Survivor — a mid-turn text that DID persist; note the single thinking record directly before it:

2026-07-15T00:17:38.440Z  thinking
2026-07-15T00:17:38.492Z  text[37 chars]
2026-07-15T00:17:43.001Z  tool_use(Edit)
2026-07-15T00:17:59.316Z  tool_use(Edit)

Reliably persisted in every turn: the first text block of the turn (before any tool call) and the turn-final text block. Reliably dropped: mid-turn texts whose response carries an adjacent interleaved thinking block (the dominant case with this model).

Impact

  • Users act on AskUserQuestion dialogs without the analysis written for them, and cannot recover it via Ctrl+O (the transcript viewer reads the same incomplete file).
  • Local --resume reconstructs context without these blocks — permanent context loss, not just a rendering gap.

Repro (best effort)

  1. Claude Code v2.1.210 with a model that produces interleaved thinking (e.g. claude-fable-5).
  2. Run a multi-step task so the assistant narrates between tool batches, ideally ending in an AskUserQuestion.
  3. grep the session .jsonl for a distinctive phrase from the mid-turn narration → 0 matches; only turn-opening and turn-final texts are present.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MKEA83HXWJrrMzCCt95FwD

View original on GitHub ↗