Repository navigation
Closed as not planned
Closed as not planned
Copy link
Description
Bug Description
UnknownError: prompt_async failed occurs due to a race condition between session lifecycle (cancel/idle) and automatic prompt submission. This happens in two scenarios:
- Todo Continuation: AI completes all agentic loop steps → session exits loop and gets cancelled → TUI detects pending todos → auto-triggers
prompt_async→ session is already in cancelled/idle state → UnknownError - Question/ESC dismiss: AI presents a Question tool with options → user presses ESC to dismiss → abort fires → session goes idle → an immediate
prompt_asyncis sent → UnknownError
Reproduction
Scenario 1: Todo Continuation (most common)
- Start a session with a work plan that has pending TODO items
- Let the AI agent complete its agentic loop (step N → "exiting loop")
- Session gets cancelled and goes idle
- TUI detects remaining todos and auto-fires
prompt_async(Todo Continuation) prompt_asyncfails because session is already in cancelled/idle state- Error:
UnknownError prompt_async failed
Scenario 2: ESC on Question
- AI uses the
Questiontool to present selectable options to the user - User presses ESC to dismiss the question (instead of selecting an option)
- TUI sends
POST /session/{id}/abort - Session transitions to cancelled/idle
- Immediately after, a
prompt_asyncis fired (likely from queued/resumed operation) - Error:
UnknownError prompt_async failed
Logs
Scenario 1 — Todo Continuation (from log 2026-03-30T103243.log, session ses_2c1595b7cffeNCN7U4nFQfGGda)
12:23:00 step=22 loop ← AI completes final agentic step
12:23:01 exiting loop ← Loop exits normally
12:23:01 compaction pruning
12:23:01 session.prompt cancel ← Session marked as cancelled
12:23:01 session.idle ← Session enters idle state
12:23:01 command.executed ← Command completes
12:23:01 GET /session/.../todo ← TUI fetches todo list (finds pending items)
12:23:01 GET /session/.../message
12:23:01 POST /session/.../prompt_async ← TUI auto-triggers Todo Continuation
12:23:01 ERROR UnknownError prompt_async failed ← ❌ Session is already cancelled!
12:23:13 step=0 loop ← Second continuation attempt starts
12:23:27 step=1 loop
12:23:28 exiting loop ← Exits again
12:23:28 POST /session/.../prompt_async
12:23:28 ERROR UnknownError prompt_async failed ← ❌ Same error again!
This happened twice in the same session within ~27 seconds.
Scenario 2 — ESC on Question (from log 2026-03-30T124351.log, session ses_2c13a106effeokLMx959pcfGgf)
12:58:16 message.part.delta (continuous) ← AI streaming output with Question tool
... (user inactivity, Question displayed) ...
13:10:54 POST /session/.../abort ← User pressed ESC
13:10:54 session.prompt cancel ← Cancel signal
13:10:54 session.idle ← Goes idle
13:10:54 abort completed (3ms)
13:10:54 POST /session/.../prompt_async ← Immediate prompt_async
13:10:54 ERROR UnknownError prompt_async failed ← ❌ Race condition!
13:10:54 ERROR Aborted process
This happened 3 times in the same session (13:10:54, 13:11:00, 13:12:05).
Expected Behavior
- Todo Continuation: When the session is in cancelled/idle state, Todo Continuation should either skip the auto-prompt, or re-initialize the session properly before sending
prompt_async. - ESC on Question: Dismissing a Question should not cascade into a
prompt_asyncerror. The abort should consume any queued prompt operations.
Environment
- OpenCode: v1.3.x (oh-my-opencode 3.14.0)
- OS: Linux
- Backend: Running with multiple LLM providers
Root Cause Analysis
The core issue is a state lifecycle race condition:
- Session transitions:
active→cancelling→idle prompt_asyncis dispatched after cancel but before the session is ready to accept new prompts- No guard exists to check session state before dispatching
prompt_async
Suggested Fix
Add a session state check in prompt_async handler:
// Before executing prompt_async, verify session is in a valid state
if (session.state === 'cancelled' || session.state === 'idle') {
// Option A: Re-initialize session then proceed
await session.reinitialize();
// Option B: Silently ignore and don't fire
return;
}Alternatively, the Todo Continuation mechanism should wait for the session to fully settle (post-cancel cleanup) before auto-firing.
Workaround
Run /stop-continuation to disable Todo Continuation before the AI completes its loop. For ESC dismissals, no workaround currently exists (the error is harmless but noisy).
Metadata
Metadata
Assignees
Labels
No labels
Activity
github-actions commentedon Mar 31, 2026
This issue might be a duplicate of existing issues. Please check:
start()) that may be related to the underlying causePlease review those issues to see if your report adds new information or is already tracked there.
zswll2 commentedon Mar 31, 2026
Closing as duplicate of #20095. Supplementary information (Todo Continuation trigger path + full log timelines) has been added to that issue: #20095 (comment)