Repository navigation
[Bug] task tool causes parent session abort — both parallel and sequential dispatch #23404
Description
Description
The task tool reliably terminates the parent session regardless of whether it is dispatched in parallel or sequentially. The subagent runs to completion, but the parent session ends with finish=NULL and 0 output tokens — all steps following the task call are silently dropped.
This makes the task tool effectively unusable in any multi-step parent workflow (e.g. scheduled routines, orchestrators, command files).
Behavior
Parallel dispatch (task + another tool call in the same turn):
- Parent ends immediately with 0 output tokens,
finish=NULL - Subagent runs, parent never receives result
Sequential dispatch (single task call, nothing else in the turn):
- Same outcome — parent ends with 0 output tokens,
finish=NULLafter thetasktool call - Subagent runs to completion, result is never propagated back
In both cases the subagent session is written to the DB and contains valid output. The parent session record exists but has no assistant messages after the task dispatch.
Root Cause (suspected)
The parent session loses its session ID context when SessionPrompt.prompt() is called for the subagent — originally documented in #13910. PR #13958 addressed the error path (missing task_id on failure) but was closed without merge on 2026-03-07.
The abort on the success path suggests the issue is broader: even a successful subagent return does not reliably resume the parent session. The session context appears to be discarded after task dispatches regardless of outcome.
Impact
- Scheduled routines / orchestrator agents cannot delegate to subagents — all steps after the first
taskcall are silently skipped - Multi-step command files with
@agentnamedelegation break after the first delegation - No error surfaced — the parent session ends silently, making debugging extremely difficult
- Workaround: inline all logic into the parent session, no subagent delegation at all — this defeats the purpose of the
tasktool entirely
Reproduction
- Create a command file with two sequential steps:
- Step 1: dispatch a subagent via
tasktool (any prompt) - Step 2: any follow-up action (write a file, send a message, etc.)
- Step 1: dispatch a subagent via
- Run the command:
opencode run --command <name> - Observe: subagent in Step 1 completes, Step 2 is never executed
- Check DB:
SELECT finish, COUNT(*) FROM message WHERE session_id = '<parent_id>'— parent has 0 output tokens after the task dispatch
Environment
- OpenCode v1.14.17 (latest as of 2026-04-19)
- Affects all providers and models
- Confirmed on Linux (Ubuntu)
- Originally documented in [Bug] Task tool loses session ID (task_id) when sub-agent fails or is cancelled — primary agent cannot recover #13910 (auto-closed after 60 days of inactivity)
- Fix PR fix(task): return task_id when subagent run errors #13958 was submitted but closed without merge on 2026-03-07
Related
- [Bug] Task tool loses session ID (task_id) when sub-agent fails or is cancelled — primary agent cannot recover #13910 — original report (auto-closed)
- fix(task): return task_id when subagent run errors #13958 — fix PR (closed without merge)
- Subagent AI_APICallError is silently swallowed, causing session to hang #13395 — subagent error silently swallowed
- Explore subagent hangs indefinitely with Anthropic Claude Opus 4.6 -- no timeout or recovery #13841 — subagent hangs indefinitely
- main agent hangs because of subagent (explore) #9003 — main agent hangs because of subagent
Activity
github-actions commentedon Apr 19, 2026
This issue might be a duplicate of existing issues. Please check:
If your issue is distinct (e.g. the parent session ends with
finish=NULLand 0 output tokens rather than hanging indefinitely), please clarify the difference so these can remain separate. Otherwise, consider adding your findings to one of the above.tbrandenburg commentedon Apr 19, 2026
Thanks for the cross-references. Having looked at both issues, I believe this report is distinct — here is the difference:
#21250 and #23296 both describe a hang: the parent session stays in
Thinkingstate indefinitely, waiting for a child task that never resolves. The parent process is still alive but blocked.This issue describes a silent exit: the parent session does not hang — it terminates cleanly and immediately after the
tasktool call. The session record in the DB showsfinish=NULLwith 0 output tokens on the parent, while the subagent session completes successfully and has normal output. There is no blocking, no stall, no timeout — the parent just stops existing.The failure modes are:
completed=nullFrom a root-cause perspective, #21250's
completed=nullempty assistant run is a different codepath than what we see here. In our case the child session is fine — it's the parent session resumption afterSessionPrompt.prompt()returns that never happens.The DB signature that distinguishes this case:
Happy to keep this separate or merge into whichever issue the maintainers think best fits — but the symptom and likely fix location differ from the hang cases.
tbrandenburg commentedon Apr 19, 2026
Verdict
Confirmed and reproduced via code analysis. The bug is real and affects all
tasktool dispatches regardless of parallel vs sequential.Root Cause
The core problem is a race between the Effect
runLoopand the AI SDK's tool execution pipeline.Here's what happens:
runLoop, LLM responds with atasktool call, stream ends withfinish_reason=tool_callshandle.process()returns"continue"torunLoop— the loop immediately advances to the next iterationtasktool'sexecute()async function in the background, waiting for the subagent to complete (could take minutes)runLoophits the next iteration, seesfinish="tool-calls", tries to build the next LLM request — but thetasktool result hasn't been written to message history yet (the subagent hasn't finished)stop, the loop exitsfinish=NULL, 0 output tokens — done, silentlyThe fundamental mismatch:
runLooponly waits for the LLM stream to end, not for tool promises to resolve. Every other tool is fast enough that this race doesn't matter in practice.taskis the only tool that re-entersSessionPrompt.prompt()and blocks for a long time, making the race reliably loseable.The fix needs to ensure
runLoopdoesn't advance to the next LLM call until all tool promises — includingtask's — have resolved and their results are committed to message history. Most likely fix location:packages/opencode/src/session/processor.ts, wherehandle.process()signals completion back to the loop.iatsiuk commentedon May 4, 2026
cannot reproduce on current dev (HEAD 2c819f2, ai@6.0.168). added a mock-driven regression test that drives parent.loop with a task tool call (and a 2-sequential variant) - both pass.
ai sdk 6.x awaits every tool execute() promise before emitting finish-step, so
Stream.runDrainin processor.ts:683 only returns after every tool-result has been handled by completeToolCall. the race described in the root-cause comment is not reachable through that contract (landed in #18433, 2026-03-27).github-actions commentedon Jul 5, 2026
To stay organized issues are automatically closed after 60 days of no activity. If the issue is still relevant please open a new one.