Repository navigation
[Bug]: OpenCode timeout error formatting crashes and skips session recovery #12456
Description
Activity
Triage
Confirmed bug in current
main(9ea9c3d5). This is not a duplicate, and it is not fixed by the open OpenCode recovery PRs.When OpenCode is unresponsive,
sendTurntimes outsession.promptAsync(10s) and then the cleanupsession.abort(1s).openCodeRuntimeErrorDetailis invoked onCause.squash(cleanupExit.cause)beforeschedulePromptAdmissionRecovery. The formatter assumes everyErrorhas a stringmessage:if (cause instanceof Error && cause.message.trim().length > 0) return cause.message.trim();
If
messageis missing or not a string, that throwsTypeError: Cannot read properties of undefined (reading 'trim'). The useful timeout is replaced by a defect, recovery never runs, and later messages fail the same way (~11s). That matches the nightly0.0.43-nightly.20260917.1866traces.The reporter’s snippet still throws against current source. The installed-runtime trigger is Effect
TimeoutError: the constructor doessuper({ message }), andData.Errorassigns that field onto the instance.new TimeoutError()(no argument) is anErrorwithmessage === undefined. Current tree Effect (4.0.0-rc.115) now passesOperation timed out after '…', so a live timeout here may not throw — the formatter is still unsafe, and nightly1866still used the no-message constructor.Related PRs do not fix this:
- fix(server): reconcile delayed OpenCode prompt admission #11613 — delayed admission grace only
- fix(server): prevent premature OpenCode turn completion #10805 — premature completion; adds another
openCodeRuntimeErrorDetailcall - fix(server): recover OpenCode turns from live busy status #11640, fix(server): open a new OpenCode turn after the provider goes idle #11090, fix(server): OpenCode turns no longer settle before OpenCode starts the prompt #11677 — other recovery/idle work; none guard
cause.message
Same throw site exists in
failPromptAdmissionRecovery(cleanup abort formatting can skipemitUnexpectedExit). There are no tests foropenCodeRuntimeErrorDetail.Suggested fix
Guard
cause.messageas a string before.trim()(same pattern aslegacySetupFailureDescriptioninapps/server/src/ws.ts). Keep the existing object /String(cause)fallbacks. Cover:openCodeRuntimeErrorDetailwithundefined/ non-stringmessage(must return a string, never throw)- prompt-timeout + abort-timeout still emits the cleanup warning and schedules prompt-admission recovery
Do not wait on #11613 / #10805. Original OpenCode disconnect cause is unknown and separate from this formatter crash.
No verified workaround for the stuck thread. A new thread or server restart may unblock that session only.
- addedbugSomething is broken or behaving incorrectly.Something is broken or behaving incorrectly.acceptedfeature request acceptedfeature request acceptedvia-triageFiled through npx t3 triageFiled through npx t3 triage
on Sep 18, 2026

Before submitting
Area
apps/server
Summary
When an OpenCode prompt submission and its cleanup abort both time out,
openCodeRuntimeErrorDetailthrows while formatting the timeout. This replaces the useful timeout error with aTypeErrorand preventsschedulePromptAdmissionRecoveryfrom running. Repeated follow-up messages fail through the same path.Steps to reproduce
The observed integration sequence was:
OpenCode connection lost. Reconnecting.session.promptAsynchits its 10-second timeout.session.abortrequest hits its 1-second timeout.The trigger for the original OpenCode connection failure is not established. The error-formatting failure is independently reproducible with the current source:
The installed T3 runtime contains an Effect
TimeoutErrorconstructor that callssuper({ message }), while its timeout implementation callsnew TimeoutError()without a message. That produces the error shape above. The worktree's newer Effect dependency supplies a timeout message, so triggering a normal timeout there alone does not reproduce the installed-runtime behavior.Expected behavior
Report the original submission and cleanup timeouts without throwing from the diagnostic formatter. Execute the intended recovery path so a failed request does not leave subsequent messages failing against stale session state.
Actual behavior
Three follow-up messages at 12:27, 12:32, and 12:49 UTC on September 18 failed after approximately 11 seconds each with the same
TypeError. No follow-up user message reached the persisted OpenCode conversation. The T3 thread eventually recorded a stopped session.Impact
Blocks work completely in the affected thread.
Version or commit
T3 Code desktop
0.0.43-nightly.20260917.1866.Installed WSL runtime artifact:
sha256-92d4c19e9d405a67bd9e5dd39f2dcc4727577472b804acebc679556824c3ed70.The unsafe formatter is also present in source at commit
19672fcf7b9aac6130133ab26f92c382d529399dand predates that branch's merge.Environment
Windows desktop, WSL Linux server, OpenCode
1.18.31, provider/modelgithub-copilot/gpt-6-astra.Logs or stack traces
Relevant trace durations from one failed follow-up:
Investigation
apps/server/src/provider/opencodeRuntime.tsassumescause.messageis a string whenevercause instanceof Error:apps/server/src/provider/Layers/OpenCodeAdapter.tscalls the formatter onCause.squash(cleanupExit.cause)before callingschedulePromptAdmissionRecovery. The formatter's exception skips that recovery call.A focused fix should handle missing or non-string error messages and cover the combined prompt-timeout/abort-timeout recovery path in a regression test.
Workaround
No verified workaround for the affected thread yet. The repository changes were committed locally and remained intact.