Repository navigation
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/web
Steps to reproduce
- Open a thread long enough that the client loads a bounded snapshot (
hasMoreHistory: true). - While a run is busy, queue one or more follow-ups. Each gets its run ordinal when it is queued.
- Before the queue drains, send messages that start right away (stop, steer, or a new turn after an interrupt). These get higher ordinals and render normally.
- Let the queued runs drain. They start and complete, and the agent replies.
Expected behavior
The queued user messages and their replies appear in the open thread as they run.
Actual behavior
They never appear. The thread looks like it stopped at the last message sent directly, so the queued input looks swallowed. Runs that start afterwards render normally. Nothing is lost on the server: the queued runs complete, and their user_message and assistant_message items are in orchestration_v2_projection_turn_items.
In the affected thread, each queued run had a requestedAt 15 to 25 minutes before its startedAt. The directly sent runs between them had higher ordinals but started first.
Impact
Major degradation or frequent failure
Version or commit
0.0.46-nightly.20261007.2774 (server and desktop)
Environment
Self-hosted t3 serve on Linux arm64 with the Claude Code provider. Seen in the desktop app on a separate Linux desktop and on a Mac.
Logs or stack traces
No errors. Provider events show `command_lifecycle` queued → started → completed and `result` / `success` for each affected run.Screenshots, recordings, or supporting files
No response
Workaround
Reloading does not help in clients that had the thread open when the queued runs drained. They restore the thread from their local cache and resume with afterSequence, so the missing rows stay missing.
A fresh snapshot from the server (GET /api/orchestration/threads/:id/bounded) does include them. Because rows are ordered by ordinal, they appear above directly sent turns that actually ran earlier.
Deleting the thread's entry from the thread store in the t3code:connection-runtime IndexedDB database, then reloading, brings the turns back.
Activity
juliusmarminge commentedon Oct 7, 2026
Note
Grok responding on behalf of Julius.
Thanks for the detailed report. I can confirm this in code on main (
3143335), though I haven't reproduced it in a running app. The queued run's items are dropped on the client by the partial-timeline "older history" guard, because their ordinal comes from the run's queue-time ordinal.Mechanism
nextRunOrdinal(projection)(runs.length + 1) at queue time (Orchestrator.ts#L4850-L4851, #L347-L349). Itsuser_messageturn item is only created when the run starts, but withordinal: queuedRun.ordinal * 100(#L1584-L1623). The server then normalizes every run-scopedturn-item.updatedinto that run's band,runOrdinal * 1_000_000 + n(EventSink.ts#L309-L330, TurnItemPositionStore.ts#L58-L71). A steer or new turn sent later gets a higher run ordinal, so all of its items sort above the still-queued run's.hasMoreHistoryis true or a history cursor is open, the client applies events withpartialTimeline: trueandlatestLocalTurnOrdinal, and raises that mark on every appliedturn-item.updated(threads.ts#L501-L526). The mark starts as the max ordinal across the full projection, taken from the snapshot (threadHistoryPaging.ts#L384-L394).shouldDropMissingPartialTurnItemdrops any item that isn't already in the window and hasordinal <= latestLocalTurnOrdinal, on the assumption that it's unloaded history (orchestrationV2Projection.ts#L89-L106). Theturn-item.updatedreducer then returns the projection unchanged (#L251-L258). Once a directly sent run's items have raised the mark, every item of a lower-ordinal queued run that starts later, its user message and its reply included, falls under it and is silently dropped.lastSequence(#L221-L225), which is sent asafterSequence(#L920). The cache is thethreadstore int3code:connection-runtime(storage.ts#L41-L45), so the dropped items are never replayed.ORDER BY ordinal ASC(ProjectionStore.ts#L2666-L2675), so the queued runs land above directly sent turns that actually ran earlier. That follows from the queue-time ordinal and matches what you saw.Fix direction (not yet decided)
runIdbelongs to a run that started after the snapshot, or that was still queued in the client's projection, and insert it by ordinal as usual. That should stop the rows from vanishing. A test with a queued run N draining after run N+1's items would cover it.Workaround: what you found works. Delete the thread's entry from the
threadstore in thet3code:connection-runtimeIndexedDB, then reload, and the client fetches a fresh bounded snapshot.Related
shouldDropMissingPartialTurnItem. It keeps an item when the window already shows an earlier item of the same run. That doesn't cover this case, because a queued run that starts late has no rows in the window yet: its first item, the user message, is the one that gets dropped. The two fixes touch the same guard and should be coordinated.session-logic.ts.Mkassabov commentedon Oct 8, 2026
Also seen with the Grok provider on
0.0.46-nightly.20261008.2813(desktop app on Linux x64 plus the Android app). Both clients showed the same thing, so it isn't one stale client cache.In one thread, follow-ups queued while a run was held open (Grok background subagents, see #15489) ended up like this:
cancelledat 09:50:05–06 without ever starting a provider turn. Their user messages still exist at their original timestamps.The user saw history "rewrite": steered messages showed up out of order, and some earlier user and agent messages vanished from the timeline. The vanished agent messages are mostly the superseded-attempt folds from #15489.
Posted from a
t3 triagesession by Claude Code (Opus 5.5).