Skip to content

TUI: AskUserQuestion modal is undismissable on v1.14.50 (Esc/Ctrl-C/Ctrl-X all no-op, traps user in question loop) #28112

Closed as not planned

Description

@dawidbednarczyk

Summary

AskUserQuestion (or equivalent question/modal tool) renders a question pane that is completely undismissable under the Claude Opus 4.7 orchestrator. Esc, Ctrl-C, and Ctrl-X all no-op. Arrow keys + Enter do navigate and submit a selection, but after submission a new identical question appears, trapping the user. Worse — characters typed while attempting to recover land in the "Type your own answer" field as silent state corruption that persists across re-renders.

This is not the ESC-race issue #20095 (fixed in v1.3.3+ via the Effect/Runner migration). I am on v1.14.50 — that code path is gone. This is a new failure mode.

Closest open/closed cousins: #9284 (auto-closed stale, model-side loop), #11367, #26849, #23515 (all open UX issues).

Environment

Field Value
OpenCode version 1.14.50
Model Claude Opus 4.7 (github-copilot/claude-opus-4.7) via Copilot provider
Agent built-in Orchestrator
OS macOS 26.4.1 (Build 25E253)
Kernel Darwin 25.4.0 arm64 (Apple Silicon, T6041)
Terminal iTerm2
Multiplexer tmux 3.x on private socket (-L concierge)
MCPs connected context7, delphi, grep_app, quicker, salesforce-dx, second-brain, tech-playbook, websearch

Steps to reproduce

  1. Run an Orchestrator agent on Claude Opus 4.7 with a long-running multi-perspective workflow.
  2. The agent eventually emits a AskUserQuestion-style modal with 6 options + "Type your own answer".
  3. User presses Esc — modal does not dismiss.
  4. User presses Ctrl-C — no effect.
  5. User presses Ctrl-X — no effect.
  6. User attempts to type a free-text reply ("continue", with a typo contineu) — characters land in the "Type your own answer" field but no Enter is fired (TUI swallows it because the input is in select-mode, not text-mode).
  7. User then arrow-navigates (Down Down) to option feat: model config persistence #3 and presses Enter.
  8. Option feat: model config persistence #3 IS submitted — agent proceeds, does real work (git commit, git push, updates a status file).
  9. Agent emits "Going to waiting" and is genuinely idle.
  10. BUT the original modal is still visible, with the contineu typo still in the custom-answer field and option feat: model config persistence #3 still checkmarked from step 7. A second identical question is queued behind it. User is trapped in the loop again.

Expected

  • Esc should dismiss the modal cleanly and return to the normal prompt.
  • Ctrl-C should interrupt the in-flight question and return control to the user.
  • After a successful selection + Enter in step 7, the modal should fully tear down before the agent fires a new one.

Actual

  • Esc / Ctrl-C / Ctrl-X are dead-keys while the modal is open.
  • Free-text typed while in select-mode silently corrupts the "Type your own answer" field — the user has no visual indication this is happening, and the corruption persists across modal re-renders.
  • Submitting an option does not tear down the modal; the next question appears layered on top of the old one.
  • No CLI / API workaround documented anywhere.

Pane capture (anonymised)

┃  Done. Tier 3 P9+P10 planning artifacts committed (e375435) and pushed. ...
┃  Going to waiting.
┃
┃  What should I tackle next? Everything remaining needs your call.
┃
┃  1. Publish [report] + update PR #1
┃  2. Sub-RPI: P5/P8 LLM challenger
┃  3. Tier 3 P9 + P10 sub-RPI✓                          ← previously selected
┃  4. Decide M4 [external-tool] nightly policy
┃  5. Decide P1 FAIL bug treatment
┃  6. Pre-cache [data file]
┃  7. Type your own answer
┃     contineu                                            ← my recovery typo
┃
┃  ↑↓ select  enter submit  esc dismiss                  ← esc DOES NOT WORK
┃
▣  Orchestrator · Claude Opus 4.7 · 41.5s                 ← agent is idle

The "esc dismiss" footer hint is lying — esc is bound but does nothing.

What I had to do to recover

Kill the entire OpenCode session via external orchestrator (concierge kill <name>) and re-spawn against the same project directory. Lost only the in-flight Oracle task — committed state on disk was preserved. This should not require killing the whole session.

Cross-references

  • #9284 — agent re-asks in loop (closed stale, not fixed). Symptom overlaps but root cause may differ.
  • #20095 / #20250 — ESC race (fixed v1.3.3+). I'm on v1.14.50, so this is a new failure mode, not a regression of that fix.
  • #11367, #26849, #23515 — open UX issues on the question modal.
  • #24988 (shipped v1.14.51) — preserved text selection on question prompts, but does not address dismiss / escape.

Suggested fixes

  1. Make Esc actually fire Question.dismiss() instead of being a no-op (the footer claims it works).
  2. Make Ctrl-C always interrupt — current behavior leaves the user with no escape hatch.
  3. When the user is in option-select mode, either route stray keystrokes to the custom-answer field only if they explicitly tab/select into it, or display the typed buffer visibly so users know it's being captured.
  4. Fully tear down the previous modal before rendering a new question, so a successful submit doesn't visually overlap with the next question.

Activity

  1. simonklee commented on May 18, 2026

    @simonklee
    Member

    Thanks for reporting this issue. We'll have a look at it.

  2. dawidbednarczyk commented on May 20, 2026

    @dawidbednarczyk
    Author

    Hitting this on v1.14.50 from a tmux automation driver — confirming the bug and adding a diagnostic that may help narrow it down.

    Reproduction (tmux driver, not interactive)

    Driving an opencode session via tmux send-keys -t <session> Enter to confirm a modal. The Enter byte arrives correctly (opentui maps \r → key.name="return" at packages/core/src/lib/parse.keypress.ts:268), but the modal does not dismiss and the server logs:

    reply for unknown request  requestID=<id>
    

    (from packages/opencode/src/question/index.ts:172-175)

    Diagnostic: /question HTTP probe distinguishes orphan from live

    The opencode HTTP server exposes GET /question (and /permission). When the modal is live, the response is a non-empty array. When the modal is orphaned (server already resolved/rejected, TUI still rendering), the response is [].

    Confirmed against two sessions on v1.14.50:

    Session TUI state GET /question Behavior
    kestra-software-reports modal rendered non-empty (live) Enter could resolve, but trapped in (editing=true, confirm=true) state — see below
    agent-installation-troubleshooting modal rendered [] (orphan) Enter routes to submit() → Question.reply → log.warn("reply for unknown request") → no-op

    This split (live vs orphan) means there are two distinct failure modes behind the same visible symptom:

    1. Orphan overlay — server pending Map is empty, TUI is stale. Recovery: re-attach (as TUI permission dialog can become stale: Enter confirm does nothing while /permission returns #28312 documents) or kill+respawn the TUI process.
    2. (editing=true, confirm=true) binding trap — neither of the two useBindings blocks in packages/opencode/src/cli/cmd/tui/routes/session/question.tsx has Enter bound when store.editing=true AND confirm()=true (block A line 122 requires !confirm(), block B line 198 requires !store.editing). Reachable via mouse click on the Confirm tab while textarea is in editing mode (line 392 onMouseDown doesn't clear editing), or via the keymap rewrite landed in introduce opentui keymap as sole key/cmd engine #26053 (98f5e6e71).

    Workaround for tmux drivers

    tmux send-keys -t <session> Escape Enter
    

    The Escape clears any stuck editing flag (Escape is bound in both blocks); the Enter then fires through block B's Confirm branch. This recovers case (2) but not case (1) — for orphan overlays, a /question HTTP probe + opencode attach (per #28312) is the only path back.

    Why upgrading to v1.14.51 does not help

    $ git log --oneline v1.14.50..v1.14.51 -- packages/opencode/src/cli/cmd/tui/routes/session/question.tsx
    2a7af6acd tui: don't fire question selection on mouse-up if text is selected  (#24988)
    

    That's the entire diff. The mouse-selection guard doesn't touch Enter, dismiss, or overlay teardown. Confirms the issue persists.

    Suggested investigation

    • Either expose a TUI-side check against /question before routing Enter to submit(), or
    • Have Question.reply's "reply for unknown request" path also send a "tear down modal" signal back to the TUI so the orphan overlay self-clears.

    Happy to file a separate issue if the maintainers prefer to track the binding-trap case (2) separately from the orphan-overlay case (1).

  3. rekram1-node commented on Jun 23, 2026

    @rekram1-node
    Contributor

    Automated: closing question issues.

    GitHub Issues are for bug reports and feature requests only — questions / support are no longer tracked here.

    If this is a bug or feature request, please open a new issue with the appropriate template.

  4. rekram1-node commented on Jun 23, 2026

    @rekram1-node
    Contributor

    Reopening – this was incorrectly closed by automated question-issue cleanup. Sorry for the noise.

  5. github-actions commented on Aug 23, 2026

    @github-actions
    Contributor

    To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions