-
Notifications
You must be signed in to change notification settings - Fork 2
Closed
Labels
bugSomething isn't workingSomething isn't workingengine:claudeClaude Code CLI (Anthropic)Claude Code CLI (Anthropic)
Milestone
Description
Description
When Claude Code requests approval (ExitPlanMode), the progress message text updates to show the action but no inline keyboard buttons (Approve/Deny/Outline Plan) appear. The "Action required — approval needed" notification is sent, but the user has no way to approve or deny.
Impact
- Critical: Claude Code subprocess blocks indefinitely waiting for a control response
- User must use
/cancelto recover (if they can find it) - The stall eventually triggers liveness warnings but the session is unrecoverable
Evidence from logs
render_progress.inline_keyboard_found action_id=claude.control.3 buttons=2— renderer correctly generates approval keyboard- No
telegram.api_error,outbox.op.failed, or transport errors anywhere - Subprocess stalled for 10+ minutes at
control_requestwithidle_seconds=600
Root Cause (hypothesis)
The progress edit with the keyboard uses wait=False (fire-and-forget via outbox). The entire edit path from enqueue → outbox worker → Telegram API is invisible at info log level:
ProgressEdits._run_loopcallstransport.edit(wait=False)→ returnsNoneimmediatelyTelegramTransport.edit()seesedited is None+not wait→ returns originalref(optimistic success)last_renderedis updated as if the edit succeeded- The actual edit executes asynchronously in the outbox worker — if it fails, nobody knows
Possible failure modes:
- Telegram
editMessageTextreturns "message is not modified" if only reply_markup changed but text/entities are identical to current state - Outbox coalescing drops the keyboard edit in favour of a subsequent non-keyboard render
- Race between debounce timing and the control_request event
Observed in
- Production v0.34.2, chat
-5193338937(lba-web), 2026-03-08 ~11:35 UTC - ExitPlanMode control request, 2 button rows (Approve/Deny + Outline Plan)
Possibly introduced by
1908640(render debouncing + non-blocking notifications) — changed notification tobg_tg.start_soon(async), debounce may delay keyboard edit- Outbox priority: SEND_PRIORITY=0 < EDIT_PRIORITY=2 means the notification send executes before the keyboard edit
Related
- Progress message stuck at 'queued · 0s' — initial edit fails silently, fallback sends new message #103 (stuck "queued" message — may share same root cause of edit failures)
Files
src/untether/runner_bridge.py—ProgressEdits._run_loop(),wait=Falseedit pathsrc/untether/telegram/bridge.py—TelegramTransport.edit(), optimistic return onwait=Falsesrc/untether/telegram/outbox.py—execute_op()silent error handling
Fix needed
- Add info-level logging when
wait=Falseedits fail in the outbox worker - Log the actual Telegram API response for keyboard edits at info level
- Consider using
wait=Truefor keyboard transitions (approval buttons appearing/disappearing) since these are user-critical - Add a retry mechanism for keyboard edits that fail
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't workingengine:claudeClaude Code CLI (Anthropic)Claude Code CLI (Anthropic)