anomalyco / anomalyco/opencode
Subagent hangs after a completed bash tool call while a detached descendant process stays alive; primary sessions unaffected
@nexxeln is already working on this.
Since Sep 5, 2026.
- Dominant language
- TypeScript
- Stars
- 209k
- Forks
- 27.5k
- Avg merge
- 7h 2m
- Merged PRs (30d)
- 384
Description
Description
Subagent sessions (mode: subagent, launched via the task tool) stop issuing their next LLM request after a bash tool call that completes normally while a long-lived detached descendant process stays alive. The TUI keeps showing the command as executing, no error is surfaced, and the session only recovers when the user aborts it. The identical call pattern in a primary (mode: primary) session does not stall.
The trigger is the lingering detached process, not the tool call itself: the bash command provably finished (its own cleanup code ran to the end).
Patterns observed
- Subagent + live detached descendant at tool-call end → hang. 4/4 reproductions.
- Primary + live detached descendant holding only redirected temp-file handles → no hang.
- Primary + detached descendant that inherited the server's stdout/stderr pipes → primary wedges too (separate, understood pipe-EOF mechanism, not this report).
- Last log line of a stuck subagent is always
evaluated permission=bash ... action=allow; the nextstream ... mode=subagentline never appears; on user abort it ends witherror=Aborted stack=undefined. - Reproduces with and without a local rewrite-only plugin (hooks
tool.execute.beforeonly), so the plugin is not the cause. - Related family: #33028, #40468, #26220. Difference: there the trigger is elusive; here it is deterministic via the live-descendant condition. #40468 reproducing on Debian suggests the class is not Windows-only.
Specific case
Any bash command that leaves a long-lived detached grandchild running reproduces it. Observed with a Playwright session browser (chosen because it makes the descendant long-lived by design):
A PowerShell wrapper (the whole bash command) runs
Start-Process node <playwright-cli.js> -s=<session> open <url> -RedirectStandardOutput/-RedirectStandardError <tempfiles> -PassThru, then WaitForExit(cap), prints the captured logs, and exits. The spawned browser daemon (node + chrome tree) stays alive by design. The wrapper exits, the bash result returns, and the subagent loop stalls before its next model request. Killing the daemon afterwards does not unstick the session.
Log signature (1.18.29)
23:33:09 evaluated permission=bash pattern="& $Pw -s=oc-subagent-probe open ..." action=allow
(no further loop/stream lines for this session)
23:37:02 process session.id=ses_... error=Aborted stack=undefined <- user abort
For contrast, #33028's signature shows a stream ... mode=subagent line before the silence; here the next stream is never even started.
Steps to reproduce
- Windows 11, PowerShell 5.1, opencode 1.18.29.
- Define a subagent (mode:
subagent) and delegate a task that runs the wrapper command above through bash. - The TUI shows the open command as running;
opencode.logshows the permission evaluation, then silence. - Manual abort is the only recovery.
Questions
- What does the subagent loop wait on between a completed tool result and the next completion request?
- Is there descendant/jobs bookkeeping on the subagent path that primary sessions skip?
Happy to provide full logs, wrapper scripts, and to test patches.
Plugins
Local rewrite-only plugin (rtk.ts, tool.execute.before only); signature identical with the plugin disabled.
OpenCode version
1.18.29
Operating System
Windows 11 (10.0.26200)
Terminal
Windows Terminal
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.