Repository navigation
bash tool: timeout kills the shell but does not abandon the stdio read — call duration is unbounded #49169
Description
Description
Summary
The bash tool's timeout terminates the shell process on schedule, but then keeps reading its
stdout/stderr pipe. If the command spawned a process that inherited those handles, EOF never arrives
while that process lives — so the call blocks well past the timeout, unbounded for a long-lived server.
The returned message is also misleading: it says the command was terminated at the timeout, when in fact
substantially more wall-clock time elapsed before the call returned.
- Bounded, reproducible:
timeout: 5000→ call returned after 25.79 s - Observed in practice:
timeout: 120000→ call returned after 1842.5 s (30.7 min), and only
because the process tree was killed externally
Suggested fix
On timeout, stop awaiting stream EOF: resolve from process exit and drain stdio with a deadline, so
timeout is a hard upper bound on the call regardless of stream state. Optionally also kill the
process group / job object so descendants don't survive the timeout — they currently do, and are
never reaped.
Plugins
OMO
OpenCode version
1.18.30
Steps to reproduce
Part A — the mechanism (standalone, no opencode needed, ~25 s)
Paste into PowerShell. It appears to freeze for ~25 s; that freeze is the bug, and it self-terminates.
$inner = Join-Path $env:TEMP 'pipedemo-inner.ps1'
@'
Start-Process -FilePath "powershell.exe" `
-ArgumentList @("-NoProfile", "-Command", "Start-Sleep -Seconds 25") `
-WindowStyle Hidden `
-RedirectStandardOutput "$env:TEMP\hang-o.log" `
-RedirectStandardError "$env:TEMP\hang-e.log" | Out-Null
"INNER_SCRIPT_DONE at $(Get-Date -Format o)"
'@ | Set-Content -LiteralPath $inner -Encoding utf8
$sw = [System.Diagnostics.Stopwatch]::StartNew()
$psi = [System.Diagnostics.ProcessStartInfo]::new()
$psi.FileName = 'powershell.exe'
$psi.Arguments = "-NoProfile -File `"$inner`""
$psi.RedirectStandardOutput = $true
$psi.UseShellExecute = $false
$p = [System.Diagnostics.Process]::Start($psi)
$null = $p.WaitForExit(60000); $exitedAt = $sw.Elapsed.TotalSeconds
$out = $p.StandardOutput.ReadToEnd(); $eofAt = $sw.Elapsed.TotalSeconds
"child process EXITED: $([math]::Round($exitedAt,2)) s"
"child stdout EOF : $([math]::Round($eofAt,2)) s"
Remove-Item -LiteralPath $inner -Force -ErrorAction SilentlyContinueMeasured (Windows 11 build 26200, PowerShell 7.6.6):
child process EXITED: 0.26 s
child stdout EOF : 25.41 s
25.15 s of blocking after the child had already exited. Running the inner script directly in a
console returns in 0.58 s — the hang only appears when stdout is a pipe being read to EOF, which is
why it never reproduces interactively.
Part B — the timeout does not bound the call (through the bash tool, ~25 s)
Invoke the bash tool with timeout: 5000 and this command:
$inner = Join-Path $env:TEMP 'to-test.ps1'
@'
Start-Process -FilePath "powershell.exe" -ArgumentList @("-NoProfile","-Command","Start-Sleep -Seconds 25") -WindowStyle Hidden -RedirectStandardOutput "$env:TEMP\to-o.log" -RedirectStandardError "$env:TEMP\to-e.log" | Out-Null
"CHILD_SPAWNED"
'@ | Set-Content -LiteralPath $inner -Encoding utf8
& powershell.exe -NoProfile -File $inner
"script finished at $(Get-Date -Format o)"Expected: the call returns at ~5 s.
Actual: it returns at 25.79 s (recorded state.time.end - state.time.start), i.e. when the
detached child exits and EOF finally arrives — while reporting:
shell tool terminated command after exceeding timeout 5000 ms
The timeout did fire and did kill the shell; it simply did not stop the read. With a server in place
of Start-Sleep 25, the call never returns at all.
Screenshot and/or share link
No response
Operating System
Windows 11 Pro build 26200, AMD64
Terminal
PowerShell 7.6.6
Activity
github-actions commentedon Sep 15, 2026
This issue might be a duplicate of existing issues. Please check:
Start-Processwith-RedirectStandardOutput/-RedirectStandardErroron Windows #37838: Bash tool hangs indefinitely when PowerShell usesStart-Processwith-RedirectStandardOutput/-RedirectStandardErroron Windows (closed — nearly identical scenario to Part B of this report)Your report adds the specific observation that the
timeoutparameter does not bound the call duration (the timeout fires and kills the shell, but the read continues), and includes a reproducible measurement showing 25.79 s elapsed despitetimeout: 5000. That aspect — timeout not bounding call duration — overlaps most closely with #47350's point 2 ("The wait seems to have no timeout") and the closed issues above.If those issues don't fully cover the timeout-not-bounding-the-call angle, it may be worth cross-referencing rather than reopening.
thdxr commentedon Oct 11, 2026
Thanks for the report! OpenCode 2.0 is now out and development is focused on V2, so we're closing issues filed against OpenCode 1. Please upgrade (
opencode upgrade --major, details: https://anoma.ly/notes/opencode-2-0), and if this is still relevant on 2.0, reopen this issue or open a new one with your 2.0 version.— from 𝕺𝖕𝖊𝖓𝕮𝖔𝖉𝖊