Concurrent AskUserQuestion calls: covered dialog loses unsubmitted selections and Other text when re-presented

Status Open
Reported on v2.1.251
Maintainer reply None cached
Activity 0 comments · opened Aug 29, 2026

Related issues

Searched before filing. Nothing found covers this trigger, but several are adjacent and the distinction matters for triage.

  • #52378 (closed, not planned) asked for async queueing: the turn would complete on submission so the agent could keep working while later forms wait. This report does not ask for that. Blocking semantics would stay exactly as they are today.
  • #86738 (open, reproduced), #81223 (open) and #73650 (closed) are the same failure class: a dialog takes over while the user is typing and the typed text is silently discarded. Their trigger is a dialog appearing over the prompt box, or a card being dismissed. The trigger here is a second AskUserQuestion call in the same turn covering the first one, which none of them cover.

Bug Description

When the model makes several AskUserQuestion calls in one turn, each new dialog covers the previous one instead of queueing behind it.

The covered call is not lost: it comes back once the dialog on top has been answered. The problem is that it comes back from scratch. Any selection the user had already made, and any text they had already typed into the "Other" field, is cleared. There is no warning, and nothing on screen indicates that anything was discarded, so the user does not realize the text they typed is gone.

What is lost:

  • Submitted answers are not lost, and no call is dropped. What is lost is input that had not been submitted yet.
  • A cleared selection costs one keypress to redo. Cleared free text is real data loss, and the "Other" field supports multiline input and an external editor (Ctrl+G), so what the user typed may be substantial.
  • No prompt, warning, or recovery.

Steps to Reproduce

  1. Get the model to make two AskUserQuestion calls in the same turn. Asking it directly works: "make two parallel AskUserQuestion calls, two questions in the first and one in the second". The first call has two questions, one of which needs the "Other" free-text field; the second call has one question.
  2. The first call's dialog renders and is interactive. Answer its first question, then on the second question choose "Other" and type some text. Do not submit.
  3. The second call's dialog renders and covers the first.
  4. Answer the second dialog normally.
  5. The first dialog returns, but from scratch: the "Other" field is empty and the selection has to be made again.

Control: if the first call is submitted before it gets covered, it does not return and its answers settle normally. So the loss only affects unsubmitted progress.

Likely mechanism

Offered for triage. The first two points come from reading the bundled JS in the shipped binary (2.1.251); the third is an inference connecting them to the observed timing.

  • The AskUserQuestion tool definition declares itself concurrency safe (isConcurrencySafe returns true), so consecutive calls in one assistant message are grouped and dispatched in parallel, capped by CLAUDE_CODE_MAX_TOOL_USE_CONCURRENCY (default 10).
  • In auto mode, each call's permission decision goes through a classifier round trip, and those round trips are serialized per agent.
  • Inference: together these render the dialogs in call order, roughly one classifier round trip apart. That gap is wide enough for the user to start answering the first dialog before the second one lands on top of it.

This is probably not specific to auto mode. The classifier round trip only sets how wide the gap is; the covering and the state reset on re-presentation should live in the dialog layer. Outside auto mode the gap is narrower, and whether it is still reachable has not been tested.

Expected Behavior

Primary: do not discard in-progress state. When a covered dialog is restored, the selections the user already made and the text they already typed into "Other" should still be there. This is the actual data loss, and it is fixable without changing any interaction model.

Secondary: queue instead of covering. A later call would render only once the active dialog has been answered, which prevents the situation entirely. To be explicit, this is not the async proposal in #52378: the turn would still block until every call is answered, exactly as it does today, and only the painting order would change.

Queueing costs no turn latency. The model receives nothing until every AskUserQuestion in the turn has been answered; all results arrive together, and the turn is blocked on the last dialog either way. (That is an observation from this session, not something read in the code.) Rendering the later dialogs early therefore gets neither the model nor the user an answer any sooner. It only produces the covering and the lost input.

Ideally the resulting behavior would be consistent across the CLI, desktop app, VS Code extension, web client, and mobile app.

Environment Info

  • Platform: darwin 25.5.0
  • Terminal: Otty
  • Version: 2.1.251
  • Permission mode: auto

Scope of testing

The input loss described here was only tested in the terminal CLI: reproduced twice, plus one control run confirming that a call submitted before being covered is unaffected.

Dialogs covering each other between concurrent calls has also been observed in the mobile app on an earlier occasion (client version not recorded), so the covering itself is not CLI specific. Whether unsubmitted input is cleared there as well has not been tested. The desktop app, the VS Code extension, and the web client have not been tested at all.

View original on GitHub ↗