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/server
Steps to reproduce
- Enable "Continue threads after server update" (
continueThreadsAfterServerUpdate: true, global, no project overrides). - Have several threads running at the same time, at least one on Codex and at least one on Claude. All Codex threads are bound to the single shared session
provider-session:provider-instance:codex:shared. - Restart the service (
systemctl --user restart t3code.service) in a way whereprepareForShutdowndoes not record any continuations before the launcher force-kills the server. In our case the server was under load (event loop stalls of 2–20 s), and the launcher's fixedTERMINATE_GRACE_MS = 5_000inapps/server/src/serviceLauncher.tsSIGKILLed it about 5.4 s afterStopping. - Wait for startup reconciliation.
Expected behavior
Every root run that was running when the server went down gets a restart-continuation ("Continue where you left off."), regardless of provider.
Actual behavior
Only Claude threads were continued. Every Codex run was cancelled by startup reconciliation and never got a continuation. That covered one top-level thread and five delegated tasks across two projects.
Cause, from reading ProviderRuntimeRecoveryService.reconcile("startup") and restartContinuationRun:
- Reconciliation runs per thread, sequentially. For each thread,
reconcileProjectionemitsprovider-session.updated → stoppedfor every bound session that is not stopped yet. - Claude has one session per thread, so each Claude thread still sees its own session as
readywhenrestartContinuationRunevaluates it. - Codex threads all share
provider-session:provider-instance:codex:shared. The first reconciled thread bound to it, an old idle thread with no active run, marked the shared sessionstopped. Every Codex thread reconciled after it then failed this check, so it got no continuation:(liveTurnRequired && (session.status === "stopped" || session.status === "error"))
The shutdown path (prepareForShutdown) does not have this problem, because it runs while sessions are still live. In an earlier restart the same day it finished in time (continuation effects written ~4.5–4.8 s after Stopping), and six Codex runs were continued correctly. The startup fallback is the path that skips Codex, and it is the only path left whenever shutdown preparation does not finish within the 5 s grace.
From reading the code, both points still apply on main @ 4ee6bfd: the reconcile loop still stops bound sessions per thread, restartContinuationRun still rejects a stopped session, and TERMINATE_GRACE_MS is still 5_000. main now calls recoverDelegatedTask for declined continuations, which should at least report back to the parent. I did not reproduce this on main.
Possible directions:
- Evaluate continuation eligibility for all threads before emitting any session stops. Alternatively, do not stop a shared session in a per-thread reconcile while other bound threads have running runs.
- Make the launcher's terminate grace configurable or longer, or let
prepareForShutdownrun before the grace timer starts.
Impact
Major degradation or frequent failure
Version or commit
0.0.46-preview.20261002.2598 (source b37fcea); code paths also checked on main @ 4ee6bfd
Environment
Linux (Debian LXC), official @t3code/t3-linux-x64 executable under systemd (KillMode=mixed, TimeoutStopSec=90s), Codex app-server provider (shared session) + Claude Agent provider
Logs or stack traces
# systemd journal, local time (UTC+2): launcher force-kills after ~5.4 s
22:03:13.195 systemd: Stopping t3code.service - T3 Code server...
22:03:18.656 systemd: t3code.service: Killing process ... (codex) with signal SIGKILL.
# no effect:restart-continuation rows with command:restart-prepare:* for this restart
# provider-session.updated events during startup reconcile (UTC)
20:03:30.891 provider-session:provider-instance:codex:shared stopped command:runtime-reconcile:startup:<idle codex thread>
20:03:33-39 provider-session:provider-instance:claudeAgent:thread:<id>:<id> stopped (one per Claude thread)
# resulting restart-continuation effects: 5, all claudeAgent
# runs cancelled by this restart with no continuation: 6 codexWorkaround
Manually send a follow-up message to each interrupted Codex thread, or have the parent re-delegate the task.
Activity
juliusmarminge commentedon Oct 4, 2026
Note
Grok responding on behalf of Julius.
Triage
Thanks for the really thorough investigation, @Dropje97! Your journal and event timeline lined up exactly with the code.
What I found
Confirmed on
main@4ee6bfd50ef4.provider-session:provider-instance:<instance>:shared.IdAllocator.derive.providerSession, which is used whensupportsMultipleProviderThreadsPerSessionis true.provider-session.updatedfrom any bound thread setsstatusfor every thread (ProjectionStore,ON CONFLICT(provider_session_id)).ProviderRuntimeRecoveryService.reconcile("startup")walks recovery threads oldest-first, and that includes idle threads still bound to a live session.reconcileProjectioncommitsprovider-session.updated → stoppedfor every live session it sees.restartContinuationRunrejects a live turn once that session isstoppedorerror.prepareForShutdownrecords continuations while sessions are still live, so it avoids the problem. ButterminateChildinapps/server/src/serviceLauncher.tssends SIGKILLTERMINATE_GRACE_MS(5000 ms) after SIGTERM, and systemd'sTimeoutStopSecdoesn't extend that. A stalled event loop can miss the window, which leaves only the startup path.recoverDelegatedTaskdoesn't cover these runs. It only runs after aprovider-runtime.continueeffect was written and then declined. The skipped Codex runs never get that effect.Likely fix area
ProviderRuntimeRecoveryService, evaluate continuation eligibility for every bound thread before any thread commits a stop on a shared session.TERMINATE_GRACE_MS(longer, configurable, or started afterprepareForShutdowncompletes). This would make the startup fallback rarer but wouldn't fix it on its own.A maintainer will decide on the fix direction.
waffleflopper commentedon Oct 7, 2026
Another occurrence, on a different install: the Linux desktop app restarted by its in-app updater, not systemd.
What happened: A Codex (gpt-6.1-sol) thread was mid-turn, waiting on a native Codex subagent, when the desktop updater restarted the app. "Continue threads after restarts" is on. After the restart the thread was settled, the subagent was cancelled, and nothing resumed it. I had to send "continue where we left off" by hand.
Evidence (UTC, 2026-10-07):
running: its attempt, root node and provider turn were all still open and were cancelled by startup reconcile at04:56:37.147Z. Its native subagent (/root/personnel_native) was cancelled at the same moment.04:56:30.68Z. There is nocommand:restart-prepare:*effect for this restart, soprepareForShutdowndidn't finish on the desktop either.provider-session:provider-instance:codex:shared, at04:56:36.740Z. The running thread was processed at04:56:37.147Z, and noprovider-runtime.continueeffect was written for it.restart-prepareand startup effects both present), which fits the order-dependent failure described here.Environment: T3 Code desktop
0.0.46-nightly.20261006.2752(d8d037e), Linux x64 (Arch / Omarchy, kernel 7.2.3), installed from GitHub releases, nightly channel, Codex provider with a shared session.So the startup fallback hits desktop updater restarts too, not just systemd's 5 s grace. #15820 looks like it covers the startup half.
Investigated and drafted with Claude Opus 5.5 (claude-opus-5-5) in Claude Code via
t3 triage.moritzwesemann commentedon Oct 9, 2026
Also seeing this on macOS 27.0.1 (arm64), desktop nightly
0.0.46-nightly.20261009.2873, using Codex /gpt-6.1-sol.During an in-app update on October 9, three active Codex threads stopped despite
continueThreadsAfterServerUpdate: trueand no project override. All resumed after I manually sent “continue.”Local traces and read-only database checks show:
15:46:27.137–15:46:27.245Z.terminalizedRuns: 3,stoppedSessions: 2,requeuedEffects: 0.This matches the shared-session failure described here. I haven’t tested #15820.
Investigated with Codex (
gpt-6.1-sol).t3dotgg commentedon Oct 21, 2026
Note
🤖 Claude Opus 5.5 responding on behalf of Theo
Thanks for the report. This is fixed on main in #19750. Please test on the nightly built from main on 2026-10-21, or on the next stable release. If the problem still occurs there, please open a new issue that links to this one, with your version and steps to reproduce it.