Repository navigation
Description
What happened
While attempting to revert a conversation to an earlier message and switching threads during the operation, the Windows desktop app reported:
The provider could not roll back this conversation. Try again; if it keeps failing, check the provider and server logs.
The timeline displayed “Run interrupted before provider start,” but the original Claude turn continued executing tools, compacting context, and eventually asking a question.
A follow-up message failed because the previous provider turn was still active. Repeated rollback attempts failed for the same reason.
The original provider turn eventually completed successfully, while its application run remained marked interrupted. Successful rollback or follow-up submission after that completion was not verified.
From the failed revert onward, I could neither continue the session normally nor read the agent’s latest responses in T3 Code. Although the provider logs show that Claude continued working and eventually completed, that did not restore normal access to the conversation in the UI.
Diagnosis
The application run and provider execution diverged:
- Application run 100 was marked
interrupted. - Its
provider-turn.starteffect was markedcancelled, with a reason stating that interruption occurred before the provider turn started. - Claude subsequently emitted tool, compaction, and question events for that same run.
- The adapter rejected rollback and another turn because it retained an active provider turn.
- Follow-up run 101 was marked
failed.
Relevant code in release commit 044f07257c9684ae4543bd1e1ebf9c394e9e3830:
- Orchestrator.ts:9710 selects the “before provider start” interruption path when no matching provider turn is found.
- Orchestrator.ts:9806 marks the run interrupted and requests cancellation of start/restart effects.
- The Claude adapter rejects rollback and another turn while
activeTurnis non-null.
This is consistent with a startup/interruption race. The precise cancellation or event-ingestion interleaving remains unverified. Cancellation machinery exists; the evidence does not establish why it failed to stop this provider execution.
Steps to reproduce
Observed sequence from one incident; not independently reproduced:
- A new message was submitted in an existing Claude conversation.
- The user attempted to revert to an earlier message and switched threads during the operation. The trace records
thread.stopapproximately two seconds after message dispatch, followed bycheckpoint.rollback. It does not establish a separate manual Stop click. - Rollback failed, while the timeline reported that the run had been interrupted before provider start.
- Sending “Continue where you left off” failed because the previous provider turn was still active.
- The original turn continued and produced an
AskUserQuestionprompt.
Whether switching threads contributes to the failure is unknown.
Expected: after Stop, provider execution and application state should settle consistently. While cancellation is pending, the UI should reflect that work remains active rather than reporting it as already interrupted.
Version
Local backend 0.1.2, verified during triage. Triage CLI version, separately: 0.1.2-nightly.20261022.3541.
Environment
Windows x64, build 10.0.26200. T3 Code desktop app with local backend. Provider: claudeAgent. Claude Code 2.1.311, reported by the provider’s initialization event. Model: claude-fable-5-1. Plan mode, High effort, Full access.
Evidence
Sanitized timeline. All timestamps are UTC on 2026-10-27:
01:13:36.653 Application run 100 requested.
01:13:38.258 Server receives thread.stop.
01:13:38.373 Application run 100 marked interrupted.
01:13:38.473 provider-turn.start effect marked cancelled:
"interrupted before its provider turn started"
01:13:38.807 Claude emits system/init.
01:13:39.927 Rollback rejected: provider turn is active.
After interruption, the original provider session continues
emitting tool calls and tool results.
01:18:17.344 Starting run 101 rejected: previous turn still active.
01:18:44–46 Another rollback attempt fails.
01:19:14–15 Another rollback attempt fails.
01:20:06.104 Original provider session emits compact_boundary.
01:20:39.060 Original turn's user_input request recorded.
01:24:49.074 That request recorded as resolved.
01:28:15.473 Original provider emits result:
subtype=success, is_error=false.
Subsequent persisted state:
Application run 100: interrupted
Application run 101: failed
Original provider turn: completedRelated issues
#8618 describes older stop/state inconsistencies. This incident concerns Orchestration V2 and demonstrates actual Claude activity after the application run was marked interrupted, followed by rejection of rollback and new turns. An exact duplicate or released fix for this sequence was not confirmed.
Fix applied or workaround
No repair was performed during triage. Investigation used read-only database queries, logs, and the existing release-pinned source checkout.
The original provider turn eventually completed successfully. That completion does not establish that rollback or subsequent message submission recovered.
Filed by
Codex, GPT-6 family, via t3 triage. Reviewed by three dedicated agents.
Activity
jamesdchen commentedon Nov 2, 2026
Another case of the run and the provider process diverging, on v0.1.6 (Linux server,
t3 serveunder systemd). Here it led to two Claude processes running the same session at once.Timeline for one thread (server trace, UTC 2026-11-02):
03:02:21Z: a Bash tool call in the turn blocks. The host's sshfs mount had hung, and the Claude process was stuck in D state on FUSE.03:04:37Z: the user sends a follow-up. The timeline showsThe provider event stream closed unexpectedly.ClaudeAdapterV2.interruptTurnfails (ProviderAdapterInterruptError: Failed to interrupt claudeAgent provider turn …), andClaudeAdapterV2.startTurn/ClaudeAgentSdkQueryRunner.opentime out after 10 s.03:04:38Z: T3 starts a second Claude scope with--resume=<same session id>and--permission-mode bypassPermissions. The first scope, started02:59:44Zwith--session-id=<same id>, is still alive. Botht3code-claude-*.scopeunits were active together.03:06:10Z/03:06:16Z: follow-ups are refused withNo running provider turn found for active run …:ordinal:5(see Explicit steer is refused with "No running provider turn found" during run startup/completion gaps #23271).03:08:48Z: the run fails withClaude timed out while registering its MCP tools.Expected: when an interrupt fails, T3 kills the old provider process (or stops its scope) before it resumes the same session in a new one. Two processes writing to one Claude session can corrupt the transcript.
The trigger here was environmental:
--add-dirpointed at the hung FUSE mount, so the new process couldn't finish starting either. A plain hang in a tool call should cause the same divergence.🤖 Generated with Claude Code
cmaciasjimenez commentedon Nov 3, 2026
Another case, on 0.1.7-nightly.20261103.4119 (
cefb544, currently the tip ofmain): macOS arm64, desktop app with local backend,claudeAgent,claude-opus-5-5. The trigger here is different. It is steering a queued message past the automatic "on return" idle compaction, not Stop or rollback. The logs pin down the interleaving this issue left unverified.Sequence (UTC, 2026-11-03, from the event store, effect outbox, server trace and the Claude provider log)
Why the interrupt missed
queued-message.promote-to-steer->stopRunForQueuedCommand->dispatchRunInterrupt. When the projection was read, run 120 wasrunningbut had no provider turn for its active attempt yet: the Claude resume takes about 1 s, and the provider turn is recorded only once the prompt is offered. So it took theproviderTurn === undefinedbranch (Orchestrator.ts#L11405). That branch stops the provider only by cancelling unsettledprovider-turn.start/provider-turn.restarteffects (Orchestrator.ts#L11552), andcancelUnsettledonly matchespending/runningrows (EffectOutbox.ts#L452). The start effect had settled 80 ms before the command committed, so nothing was cancelled and no interrupt reached Claude. The adapter'sactiveTurnstayed set (ClaudeAdapterV2.ts#L10711), and every start was refused until the compaction ended on its own.The "before provider start" decision is made on a snapshot that can be stale by commit time. A start effect that settles in that window should lead to a real
provider-turn.interrupt, not just a cancellation of effects that have already finished.Knock-on effect (related: #28178)
At run 124,
ProviderTurnStartServiceloggedRecovering provider context in a fresh native sessionwithreason: "uncertain_history_delivery",errorTag: "ProviderAdapterTurnStartError"(ProviderTurnStartService.ts#L1326). The thread'snativeThreadRefmoved to a new, never-created session id, and afull_thread_summaryhandoff (runs 1-123) was queued with the delta handoffs. The UI showed a "Context handoff Opus 5.5 -> Opus 5.5" divider. So the native Claude session, which went on to compact successfully, is abandoned. The failures behind this were only localprevious_turn_activerefusals, and none of them reached the provider.Repro (from this one incident; not independently reproduced)
/compactfirst and queues the message.Posted from a
t3 triagesession by Claude Code (Claude Opus 5.5,claude-opus-5-5).Chinoman10 commentedon Nov 6, 2026
Corroborating this with Pi, on a Linux server running a locally patched T3 Code 0.1.6. The installed bundle already contains #27141's superseded-turn lookup. This is the same accepted-start / application-stop divergence as the November 3 comment, although the original Stop snapshot timing was not retained, so I cannot prove every internal interleaving from that incident alone.
Sanitized persisted ordering, all UTC on 2026-11-05:
The event sequence places the running provider-turn event before Stop's event batch, while Stop's attempt record still had no providerTurnId. Pi continued emitting actual tools after the application run was marked interrupted. A later T3 thread-Stop request returned no_active_run. Recovery required terminating only that thread's orphaned native runtime, preserving its session, then resuming successfully.
We reproduced the missing-turn snapshot / accepted-start race deterministically on pristine upstream
337c5858c33bc7f8f6dfd391a2c279fa0f7e4d17, using the real orchestration/outbox/session services and a controlled provider. A barrier holds Stop's missing-turn snapshot, lets startup accept and succeed, then releases Stop; upstream reports a terminal interruption while the native turn remains unresolved. This is not only an adapter timeout or a Pi-specific guard problem.The correction is now submitted as PR #31933, exact head
bac71650033ae560a28f7bf51b997b399b75ba9a. It incorporates pinned upstream202d5b56and preserves the newer EventSink/ProviderCommitBatch ingestion refactor rather than reverting it. Regression checks cover cancellation while startup is pending, delayed identity ingestion, exact-attempt isolation, definite refusals, teardown and late subscriptions. The first remote CI run exposed buffered-event and definite-preparation lifetime gaps; these were corrected without weakening the replay/recovery behavior assertions. The current exact-head changed-code check passed 499 tests and 36 affected-package typechecks; the previously failing targeted CI/replay/batching suites passed 213 tests locally. Fresh independent correction review approved this head and independently passed all 18 race cases plus 55 manager tests.An isolated actual Pi 1.5.0/Luna OAuth canary on that exact merged head confirmed authentic acceptance/streaming, nonterminal Stop, actual abort with its terminal buffered behind held ingestion, successful terminal drain/exact-runtime closure and old owner None before replacement, then replacement completion without process overlap. There were two native starts, one abort, a maximum of one live native process, and both captured PIDs were absent after cleanup. Independent review findings during development were corrected, not waived. This is controlled local evidence, not proof of every original timing or production release verification. No live backend activation, restart or selector change was performed; CI and upstream review remain separate.
AI-assisted investigation and implementation: GPT-6.1 Sol through Pi in T3 Code; bounded native canary used GPT-6 Luna through Pi subscription authentication. No private conversation contents, credentials or raw provider traces are included here.