[Bug]: Desktop 0.0.42 never opens a window — backend crash-loops on legacy thread.message-sent rows missing payload.turnId

Open
#12,762 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

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

Research direction

Start at OrchestrationEventStore.readFromSequence and rowToEvent, using the PersistenceDecodeError in server-child.log and the legacy thread.message-sent rows in ~/.t3/userdata/state.sqlite. Verify decoding of rows without payload.turnId alongside rows storing turnId as null, then launch the desktop app and confirm the backend remains ready and the window opens.

Written by the indexing model from the issue text.

Description

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

apps/desktop

Steps to reproduce
  1. Have legacy thread.message-sent rows without the payload.turnId key in ~/.t3/userdata/state.sqlite (written by an older build; in my case 55 rows, sequences 539–593, one thread, dated 2026-08-03).
  2. Launch T3 Code (Alpha) 0.0.42 on Windows.
  3. Observe: main + GPU + renderer + server processes stay alive, but no window is ever created. Restarting, clearing Cache/GPUCache, --disable-gpu, --no-sandbox, and a full reinstall (state in ~/.t3 survives it) all reproduce the same result.
  4. Check ~/.t3/userdata/logs/server-child.log: the backend child exits with code=1 and respawns roughly every ~30s with a new pid.
Expected behavior

The backend finishes replaying OrchestrationEventStore (treating a missing turnId as null, as newer rows already store explicit "turnId": null), becomes ready, and the desktop window opens.

Actual behavior

The backend throws on the first legacy row and never becomes ready, so the window is never created. All processes report no top-level window (MainWindowHandle 0).

Impact

Blocks work completely

Version or commit

T3 Code (Alpha) 0.0.42.0, update channel latest, installed at %LocalAppData%\Programs\t3code

Environment

Windows 11 10.0.26200, Ryzen 5 3600, NVIDIA RTX 5060 Ti (driver 32.0.16.1656). Backend state: ~/.t3/userdata/state.sqlite (~63 MB, 11835 rows in orchestration_events).

Logs or stack traces

One redacted crash cycle from ~/.t3/userdata/logs/server-child.log (repeats with a new pid ~every 30s):

[2026-09-20T17:53:20.733Z] ERROR backend child process failure output start | pid=22048 port=3773 cwd=C:\Users\<user>
[2026-09-20T17:53:20.740Z] INFO backend-child stdout:
[14:52:50.728] INFO (#66): Relay client process started; waiting for tunnel connection

[2026-09-20T17:53:20.752Z] INFO backend-child stdout:
[14:52:53.972] ERROR (#3): PersistenceDecodeError: Decode error in OrchestrationEventStore.readFromSequence:rowToEvent: AnyOf(Composite(Pointer(Composite(Pointer(MissingKey)))))
    at PersistenceDecodeError.fromSchemaError (file:///C:/Users/<user>/AppData/Local/Programs/t3code/resources/server.asar/apps/server/dist/bin.mjs:56348:10)
    at file:///C:/Users/<user>/AppData/Local/Programs/t3code/resources/server.asar/apps/server/dist/bin.mjs:56392:43
    at file:///C:/Users/<user>/AppData/Local/Programs/t3code/resources/server.asar/apps/server/dist/claudeHistoryWorker-CAn1PawV.mjs:10021:96
    at ~effect/Utils/internal (file:///C:/Users/<user>/AppData/Local/Programs/t3code/resources/server.asar/apps/server/dist/claudeHistoryWorker-CAn1PawV.mjs:2558:10) {
  [cause]: SchemaError: Missing key
    at ["payload"]["turnId"]
}

[2026-09-20T17:53:20.753Z] ERROR backend child process failure output end | pid=22048 code=1


DB finding: `thread.message-sent` = 1007 rows, 952 with `turnId` (newer ones explicitly `null`), 55 without the key (seq 539–593). All other event types that never had `turnId` decode fine, so the decoder requires the key specifically for this event type.
Screenshots, recordings, or supporting files

No response

Workaround

With the app closed, back up ~/.t3/userdata/state.sqlite, then backfill "turnId": null into the legacy thread.message-sent payloads missing the key. Backend became stable and the window opened immediately, with no data loss.

Suggested fix

Add a startup schema migration (or backward-compatible decode treating a missing turnId as null) for legacy thread.message-sent rows, so old state doesn't brick the desktop app in a silent crash loop.

Dominant language
TypeScript
Stars
23.3k
Forks
6k
Avg merge
10h 57m
Merged PRs (30d)
365

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.

More from pingdotgg/t3code

All issues in pingdotgg/t3code

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.