pingdotgg / pingdotgg/t3code

[Bug]: OpenCode timeout error formatting crashes and skips session recovery

Open
#12,456 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

accepted bug via-triage
Dominant language
TypeScript
Stars
23k
Forks
5.9k
Avg merge
11h 14m
Merged PRs (30d)
357

Description

Before submitting
  • I searched existing issues and did not find a duplicate.
  • I included enough detail to reproduce or investigate the problem.
Area

apps/server

Summary

When an OpenCode prompt submission and its cleanup abort both time out, openCodeRuntimeErrorDetail throws while formatting the timeout. This replaces the useful timeout error with a TypeError and prevents schedulePromptAdmissionRecovery from running. Repeated follow-up messages fail through the same path.

Steps to reproduce

The observed integration sequence was:

  1. Run a thread through the OpenCode provider in the Windows desktop app with a WSL server.
  2. The OpenCode event stream disconnects. T3 logs OpenCode connection lost. Reconnecting.
  3. Send another message while the OpenCode endpoint is unresponsive.
  4. session.promptAsync hits its 10-second timeout.
  5. The cleanup session.abort request hits its 1-second timeout.
  6. Formatting the cleanup timeout throws before T3 schedules prompt-admission recovery.

The trigger for the original OpenCode connection failure is not established. The error-formatting failure is independently reproducible with the current source:

import { openCodeRuntimeErrorDetail } from "./apps/server/src/provider/opencodeRuntime.ts";

const error = new Error();
Object.defineProperty(error, "message", { value: undefined });
openCodeRuntimeErrorDetail(error);
// TypeError: Cannot read properties of undefined (reading 'trim')

The installed T3 runtime contains an Effect TimeoutError constructor that calls super({ message }), while its timeout implementation calls new 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 19672fcf7b9aac6130133ab26f92c382d529399d and predates that branch's merge.

Environment

Windows desktop, WSL Linux server, OpenCode 1.18.31, provider/model github-copilot/gpt-6-astra.

Logs or stack traces

Relevant trace durations from one failed follow-up:

opencode.session.promptAsync  10002 ms  Interrupted
opencode.session.abort         1001 ms  Interrupted
sendTurn                      11017 ms  Failure

TypeError: Cannot read properties of undefined (reading 'trim')
    at openCodeRuntimeErrorDetail (.../t3:242573:46)
    at Array.<anonymous> (.../t3:245510:18)
    at sendTurn (.../t3:279695:40)
    at sendTurn (definition) (.../t3:245312:20)
    at sendTurn (.../t3:293056:32)
    at sendTurn (definition) (.../t3:279603:19)
    at processTurnStartRequested (.../t3:293229:89)
    at processTurnStartRequested (definition) (.../t3:292880:36)
    at processDomainEvent (.../t3:293258:46)
    at processDomainEvent (definition) (.../t3:293204:29)
Investigation
  • apps/server/src/provider/opencodeRuntime.ts assumes cause.message is a string whenever cause instanceof Error:

    if (cause instanceof Error && cause.message.trim().length > 0) return cause.message.trim();
    
  • apps/server/src/provider/Layers/OpenCodeAdapter.ts calls the formatter on Cause.squash(cleanupExit.cause) before calling schedulePromptAdmissionRecovery. 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.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in apps/server/src/provider/opencodeRuntime.ts at openCodeRuntimeErrorDetail and inspect its callers in apps/server/src/provider/Layers/OpenCodeAdapter.ts. Run the existing focused provider tests, then add regression coverage for missing error messages and the combined prompt-timeout/abort-timeout path. Done means timeout details are reported without a TypeError and schedulePromptAdmissionRecovery still runs.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.