You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
OpenCode executes a child-spawning tool after cancellation #33364
OpenCode can continue into a child-spawning tool call after a user interrupt has already been delivered, then fail to return control within the bounded run.
The standalone reproducer installs public opencode-ai@1.17.9, starts a local mock provider, schedules SIGINT 800 ms after the CLI starts, and delays the provider tool call for 2000 ms. The reproduction succeeds only when the delayed child-spawning tool call still records its PID side effect and the process exits by timeout/signal.
Plugins
None.
OpenCode version
1.17.9
Steps to reproduce
Prerequisites: Docker, Python 3, and the GitHub CLI (gh) for the clone command below. The linked reproducer is self-contained and uses only Python standard-library modules plus Docker. It installs the affected OpenCode version from the public npm package, starts a local mock provider, and runs the CLI in an isolated workspace. The Docker run is limited to 2 CPUs and 4 GiB RAM by default.
Actual behavior: OpenCode receives the user interrupt before the delayed provider tool call is sent, but the child-spawning tool still records its side effect and the CLI only exits by timeout/signal.
Expected behavior: A user interrupt should prevent later provider-stream tool calls from causing local side effects, and the CLI should return control boundedly.
Screenshot and/or share link
Not applicable. The linked reproducer prints the provider transcript checks and REPRODUCED.
Operating System
Linux x86_64 Docker, using a node:24-bookworm-based target image.
I can corroborate this at the provider-transport boundary on OpenCode 1.18.3 and 1.18.4.
Using an isolated opencode serve plus a loopback OpenAI-compatible SSE provider, I start an actual configured-model turn, wait until the provider emits a valid partial chat-completion SSE frame, then call POST /api/session/:id/interrupt.
Observed on both versions:
interrupt returns 204
/api/session/active removes the session
the loopback provider request receives neither request aborted nor response close within 5 seconds
this reproduces for both a queued and a steered delivery (2 provider requests total)
no external provider is contacted
So the application state is cleaned up, but the in-flight provider HTTP/SSE stream remains alive. That leaves a path for a late provider tool call like the one in this issue to arrive after cancellation.
The relevant cancellation files are unchanged from v1.18.3 through v1.18.4 and current dev at 4cc022481c184cb9d5e14f7e882b6749d2414553:
packages/core/src/session/run-coordinator.ts
packages/core/src/session/runner/llm.ts
packages/llm/src/route/transport/http.ts
Expected invariant: once interrupt completes, the provider response body/socket is cancelled promptly and no later provider event can be admitted or execute a tool. I can provide the self-contained TypeScript probe and secret-free JSON reports if useful.
Hi, adding a current-version recheck since this was auto-closed today.
I revalidated the original standalone Docker reproducer against the current npm latest, opencode-ai@1.18.31 (checked 2026-09-19 UTC). The only change to the repro case was updating the package/image version from 1.17.9 to 1.18.31.
Result: this still reproduces consistently for me. I ran one build run and then three --skip-build reruns against the same 1.18.31 image; all reproduced. The reruns all ended with:
process_exit=137
process_timed_out=True
provider_requests=2 to /v1/messages
side_effect_file_exists interrupt-child.pid
timeout_or_signal: returncode=137 timed_out=True
So the child-spawning tool side effect is still observed after the scheduled interrupt, and the CLI still only returns via the reproducer timeout/signal.
I also did not find a linked merged PR on this issue's timeline that directly covers #33364. Related issue #40829 still references this as the separate “tool starting after cancellation” case.
Could we reopen this as still current? If you would prefer a fresh issue because of the bot auto-close message, I can also file a new one with the 1.18.31 retest details.
Activity
JihoonJeong commentedon Jul 21, 2026
I can corroborate this at the provider-transport boundary on OpenCode 1.18.3 and 1.18.4.
Using an isolated
opencode serveplus a loopback OpenAI-compatible SSE provider, I start an actual configured-model turn, wait until the provider emits a valid partial chat-completion SSE frame, then callPOST /api/session/:id/interrupt.Observed on both versions:
/api/session/activeremoves the sessionabortednor responseclosewithin 5 secondsSo the application state is cleaned up, but the in-flight provider HTTP/SSE stream remains alive. That leaves a path for a late provider tool call like the one in this issue to arrive after cancellation.
The relevant cancellation files are unchanged from v1.18.3 through v1.18.4 and current
devat4cc022481c184cb9d5e14f7e882b6749d2414553:packages/core/src/session/run-coordinator.tspackages/core/src/session/runner/llm.tspackages/llm/src/route/transport/http.tsExpected invariant: once interrupt completes, the provider response body/socket is cancelled promptly and no later provider event can be admitted or execute a tool. I can provide the self-contained TypeScript probe and secret-free JSON reports if useful.
github-actions commentedon Sep 19, 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.
N0zoM1z0 commentedon Sep 19, 2026
Hi, adding a current-version recheck since this was auto-closed today.
I revalidated the original standalone Docker reproducer against the current npm latest,
opencode-ai@1.18.31(checked 2026-09-19 UTC). The only change to the repro case was updating the package/image version from1.17.9to1.18.31.Result: this still reproduces consistently for me. I ran one build run and then three
--skip-buildreruns against the same1.18.31image; all reproduced. The reruns all ended with:process_exit=137process_timed_out=Trueprovider_requests=2to/v1/messagesside_effect_file_exists interrupt-child.pidtimeout_or_signal: returncode=137 timed_out=TrueSo the child-spawning tool side effect is still observed after the scheduled interrupt, and the CLI still only returns via the reproducer timeout/signal.
I also did not find a linked merged PR on this issue's timeline that directly covers #33364. Related issue #40829 still references this as the separate “tool starting after cancellation” case.
Could we reopen this as still current? If you would prefer a fresh issue because of the bot auto-close message, I can also file a new one with the
1.18.31retest details.