[Bug]: Stop during OpenCode startup leaves empty session running and blocks unrelated provider starts
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
Before submitting
- I searched existing issues.
- I included enough detail to investigate the problem.
Related: #11889, #6517, #4713, #5750. This report captures an OpenCode startup/interrupt sequence on 0.0.42 that blocks subsequent provider starts across OpenCode and Codex. No thread deletion or runtime-mode change occurred in the captured sequence. It may share the cancellation cause of #11889; please merge if appropriate.
Area
apps/server
Steps to reproduce
Observed sequence, not yet a deterministic reproduction of the original race:
- Start a new OpenCode thread in a worktree on a headless T3 0.0.42 server.
- Press Stop while the provider/worktree is still starting, before the provider emits
turn.started. In this incident six interrupt requests arrived over approximately 2.5 seconds. - The session subsequently emits
session.started,thread.started, andturn.started, but OpenCode never receives a user message. - Select another model and submit a follow-up. Later try Stop again.
- Submit messages to other threads and create fresh OpenCode and Codex threads. They remain pending without provider progress.
Deterministic live check of the already-stalled server:
- Issue a temporary scoped bearer token using
t3 auth session issue. - POST
thread.createto/api/orchestration/dispatchfor a disposable health-check thread. - POST
thread.turn.startusingcliproxy/or-glm-5.3-flash, with the promptHealth check only. Do not use tools or read files. Reply exactly T3_GLM_OK. - Poll the read-only SQLite projection for an assistant response for 60 seconds.
Both dispatches return HTTP 200 with accepted sequence numbers. The check fails: no assistant response and no projection_thread_sessions row for the probe thread. This drives the affected T3 orchestration path rather than only testing HTTP availability.
Expected behavior
An interrupt during startup should settle the pending turn or report a bounded failure. It should not block provider starts in unrelated threads, including another provider. A running UI state should reconcile with an idle provider session that has never received a message.
Actual behavior
The original thread remains Thinking/Working for over an hour. Stop requests and follow-ups persist but do not resolve it. Two later threads, one OpenCode and one Codex, show starting with no active turn or resume cursor. An additional API-created probe has no session row at all.
The original OpenCode session exists but has zero messages and zero token usage. Its global health and session APIs respond. A separate direct OpenCode GLM invocation inside the same container completes successfully. This is not evidence of a GLM outage.
Impact
Blocks work completely on the affected T3 server. Existing provider work on another thread finished after the initial stall, but subsequent provider intents stopped progressing.
Version or commit
T3 v0.0.42, OpenCode 1.18.31. No local T3 source patch.
Environment
Linux x86_64, kernel 6.8.0-139-generic, Node v24.21.0. Headless T3 in a custom Kubernetes StatefulSet container, 6 GiB memory limit. The pod stayed Running with zero restarts, approximately 14 hours uptime. Mobile client displays the stalled thread. Browser/client version was not collected.
Initial turn model: cliproxy/gpt-6-astra. Follow-up selection: cliproxy/or-glm-5.3-flash. An unrelated new thread used the Codex provider with gpt-6-astra.
Logs or stack traces
Sanitized persisted event timeline, September 16, 2026, UTC. A is the original thread, B another existing thread, C/D new threads:
18:26:25.431 A thread.turn-start-requested, OpenCode/gpt-6-astra
18:26:36.587 A worktree metadata updated
18:26:41.413 through 18:26:43.865
A six thread.turn-interrupt-requested events
18:26:49.060 A provider session.started
18:26:49.061 A provider thread.started
18:26:49.132 A provider turn.started, model=cliproxy/gpt-6-astra
18:27:04.117 A thread.turn-start-requested, OpenCode/or-glm-5.3-flash
18:28:09.785 B completed existing turn
18:58:40.492 B provider session reaped for inactivity
19:21:48.247 B thread.turn-start-requested, no subsequent progress
19:22:26.833 A follow-up turn-start-requested, no progress
19:28:14.145 through 19:28:17.056
A seven more interrupt requests, no progress
19:28:51.246 C session starting, OpenCode, no active turn/resume cursor
19:30:10.139 D session starting, Codex, no active turn/resume cursor
The original per-thread provider event log contains only the three startup events above. There are no message/tool/completion events. Before the health probe, the message/session/turn projectors had all reached the latest event sequence, 12568.
GET OpenCode /global/health
{"healthy":true,"version":"1.18.31"}
GET OpenCode /session/status
{}
GET OpenCode /session/<affected-session>/message?limit=2
[]
The session status and messages were also checked with the affected
worktree in x-opencode-directory, with the same results.
Direct CLI in the same pod:
opencode run --dir /tmp --model cliproxy/or-glm-5.3-flash --format json \
'Health check only. Do not use tools. Reply exactly GLM_OK.'
=> text: GLM_OK, step-finish reason: stop
T3 API probe:
dispatch thread.create 200 {"sequence":12569}
dispatch thread.turn.start 200 {"sequence":12571}
FAIL no assistant response within 60 seconds
session []
The current upstream OpenCode adapter still contains unbounded prompt-cancellation waits involving Fiber.interrupt(admission.promptFiber) and Deferred.await(admission.submissionSettled). Together with #11889's maintainer analysis, these are investigation leads, not a proven stack trace for this incident. The fact that new threads persist and receive turn-start requests distinguishes this from a block before ThreadDeletionReactor.drainThrough completes.
Screenshots, recordings, or supporting files
The user screenshot showed the original thread with two initial prompts, a later Ping, Thinking, and Working for 1h 14m 13s. Private conversation content and infrastructure identifiers are omitted here. Relevant event and API evidence is included above.
Workaround
Recovery has not yet been attempted at filing time. Next step is restarting only the affected T3 environment after retaining evidence, then repeating the same T3 API probe. I will add the result to this issue.
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.
Research direction
Start in apps/server with the persisted event timeline and the /api/orchestration/dispatch probe, then review the upstream OpenCode adapter's prompt-cancellation waits and the analysis in #11889. Reproduce after restarting the affected environment and rerunning the health-check sequence. Done means startup interruption settles or fails boundedly, the projection records the probe session, and unrelated provider starts continue.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- kubernetes, node.js, sqlite, typescript
- Domain
- api, backend, databases, distributed-systems
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Needs clarification
- Newbie friendliness
- 35/100