[Regression bug] TranscriptEvent write delay: tool_use event not written to session.jsonl until the tool_use_result is received.

Status Closed — not planned
Reported on v2.1.119
Maintainer reply None cached
Activity 10 comments · opened May 12, 2026 · closed Aug 29, 2026

Bug Description
there is a regression I notice with your transcript event writes. the current version does not write the AskUserQuestion event to the session .jsonl on disk until after the user provides an answer. older versions (2.1.119 verified) do as expected which is write the AskUserQuestion event to disk immediately upon prompting.

Environment Info

  • Platform: win32
  • Terminal: windows-terminal
  • Version: 2.1.139
  • Feedback ID: 0b70a2ea-4db7-46a6-9927-d99e7736ca14

The prior behavior is needed so external tooling can notify the user that interaction is required to continue.

repro steps:

  • new session
  • user prompt: qna prompt test: ask me a simple question
  • wait for the question to be shown on screen
  • inspect the session .jsonl, AskUserQuestion tool_use event is missing
  • back in the session, respond to the question
  • check the .jsonl and the AskUserQuestion tool_use event will now be written, using the original ask timestamp (not the timestamp in which it's finally written to disk)

View original on GitHub ↗

9 Comments

jasonswearingen · 3 months ago

it seems like perhaps the latest transcriptEvent is not being flushed properly, as it seems other events are being delayed also

jeffgortmaker · 3 months ago

Same on Linux with version 2.1.138. On my end, this breaks a relay that tails the transcript.

Conchylicultor · 3 months ago

Also affected by this.

jshaofa-ui · 3 months ago

🔧 Root Cause Analysis & Fix Proposal

Problem

AskUserQuestion tool_use events are not written to session.jsonl until the user responds. This breaks external toolchains that tail the transcript for real-time event detection.

Root Cause

The transcript flush logic was changed to batch events — AskUserQuestion events are held until the corresponding tool_result arrives, then both are written together. This breaks the real-time event stream contract.

Suggested Fix

Separate event creation from answer association:

function onAskUserQuestion(event: ToolUseEvent) {
  writeTranscriptEvent({ ...event, answer: null, timestamp: Date.now() });
  transcriptStream.flush();  // Force immediate flush
}

function onUserAnswer(questionId: string, answer: string) {
  writeTranscriptEvent({ type: 'tool_result', tool_use_id: questionId, content: answer, timestamp: Date.now() });
}

Impact

  • Severity: High — breaks all external transcript monitoring tools
  • Regression: Yes — worked correctly in v2.1.119
  • Affected: Cross-platform (confirmed on Windows + Linux)
jasonswearingen · 3 months ago

I also see that now token usage as reported in the .jsonl does not match the claude.exe reported amount most of the time, likely because the transcript events are being withheld (not written) upon delivery anymore.

jasonswearingen · 2 months ago

This is a serious regression. When a MCP or tool call fails due to a tool hang, the toolUse event is never written to .jsonl. Then, if you interrogate Claude about the hang from another session , it will claim that you canceled before the tool was ever called. Because it never writes the tool call to jsonl so it doesn't think it happened.

jasonswearingen · 2 months ago

This is not stale. it still happens with all tool calls not being flushed to disk until after the toolUseResult is available.

jasonswearingen · 2 months ago

another nasty side effect of this bug is if your session closes before the flush, the history is lost when you resume. so it will effectively rewind your conversation to before the unflushed events took place.

VetoVetoVeto · 1 month ago

Confirming this is still present in v2.1.201 (Windows), and a note on a partial write that makes it look "half-fixed".

We build an external daemon that tails the session .jsonl to detect when an interactive session is parked on an AskUserQuestion and needs input. This regression breaks that detection exactly as described: while the modal is parked, the assistant turn containing the AskUserQuestion tool_use is not written to disk. It only appears after the user answers or cancels, batched together with the tool_result and backdated to the original invocation timestamp.

Reproduced on 2.1.201:

  • A fresh interactive session parks on an AskUserQuestion. The transcript tail remains frozen at the last user record for the entire time it is parked (observed for 30+ minutes); the thinking/text/tool_use records for the parked turn are absent.
  • Once the user answers, all of them appear at once alongside the tool_result; the tool_use retains its original invocation timestamp, showing that the completed message was buffered rather than written when it was rendered.

**Possible source of confusion — a partial record that is not the fix:** On 2.1.201, a separate {"type":"ai-title","aiTitle":"...","sessionId":"..."} record is written while the modal is parked. This is the long-standing session-title record emitted via an independent code path. It is not the tool_use event and does not contain the question or options, so it does not restore the real-time event stream. External tools still cannot see the pending question from the transcript.

Note that 2.1.200's "AskUserQuestion no longer auto-continues by default" change makes this worse in practice: modals now remain parked indefinitely instead of automatically continuing after ~60 seconds of inactivity, so the window during which the pending question is invisible to external tooling is now unbounded.

+1 on the suggested fix (write the tool_use event with answer: null, flush it immediately at invocation, and associate the answer separately). That restores the real-time contract.

Workaround for others encountering this: A PreToolUse hook configured for AskUserQuestion receives the full {questions, options} payload on stdin at tool dispatch—before the modal parks and independently of the broken transcript flush. Capturing it there (and clearing it on the corresponding PostToolUse event or when the answer arrives) is a reliable out-of-band substitute for the transcript event until the flush behavior is fixed. It is not a fix for the transcript contract itself, but it does unblock external detection today.

Environment: claude 2.1.201 (Windows 11; also observed on 2.1.195). CLAUDE_CODE_SKIP_PROMPT_HISTORY unset. Interactive CLI (not -p/headless).

Showing cached comments. Read the full discussion on GitHub ↗