[BUG] Refusal followed by terminal-only AskUserQuestion dialog blocks channel-driven sessions
Summary
In a session driven by a channel plugin (Telegram), a model refusal (stop_reason: refusal) is followed by an AskUserQuestion permission dialog that renders only in the terminal. Nobody can answer it from the channel, so the session blocks and every later channel message queues behind it until the session is restarted externally.
Environment
- Claude Code 2.1.295, Linux
- Long-running interactive session under a PTY (systemd user service),
bypassPermissionsmode - Telegram channel plugin; the channel is the only user surface
Observed sequence (happened twice on the same day)
- A turn ends with an assistant message whose
stop_reasonisrefusal(transcript JSONL). - About two seconds later the debug log shows
executePermissionRequestHooks called for tool: AskUserQuestion. - A terminal dialog appears. The session waits on it indefinitely, and new channel messages are not processed.
The transcripts contain no model-issued tool_use for AskUserQuestion around these events. The dialog therefore appears to be raised by the CLI after the refusal, not by the model.
Expected
A session whose input comes from a channel should never block on a terminal-only dialog. After a refusal the turn should end, and the next inbound message should be handled. If a follow-up question is needed, it should either be routed to the channel or skipped.
Related
The same class of problem also comes from a startup nag ("Make auto mode your default permission mode?"), which opened as a blocking terminal dialog in a fresh interactive session.
Workaround in use
A PermissionRequest hook with matcher AskUserQuestion returns {"decision": {"behavior": "deny", "interrupt": true}} when an env flag marks the session as channel-driven, plus an equivalent PreToolUse deny. In a test session this ends the turn cleanly. It has not yet been confirmed against the refusal path itself.