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
- Open a Git repository project in T3 Code (Desktop
0.1.7, commit322f6544dfad) using Antigravity (AcpAdapterV2, e.g.gemini-4-carbon, full-access). - On a thread rooted in the main checkout (
worktreePath: null), have the agent invoket3_worktree_handoffmid-turn with acontinuationPrompt(creating a new branch/worktree). - Wait for the worktree creation and observe the thread timeline, run states in SQLite, and
server.trace.ndjson. - (For comparison) Repeat step 2 using Cursor (
@cursor/sdk).
Expected behavior
The handoff turn ends cleanly without failing or hanging, and the queued worktree-continuation run starts automatically in the newly bound worktree (as fixed for Codex in #24545).
Actual behavior
Every mid-turn t3_worktree_handoff hits a lifecycle bug in RunExecutionService + ProviderSessionManager, with provider-specific symptoms:
- Antigravity (
AcpAdapterV2, reproduced 2/2 threads): The worktree is created and theworktree-continuationrun is queued (status: "queued"), but the handoff run staysstatus: "running"indefinitely (observed stuck for ~40 minutes and ~97 minutes across two threads) and the queued continuation never starts until the user manually clicks Stop (thread.stop). - Cursor (reproduced 3/3 threads): The pre-handoff run does exit and the continuation runs, but the handoff run is erroneously recorded as
status: "failed"with"The provider event stream closed unexpectedly."(ProviderAdapterEventStreamError: Workspace changed.).
Root cause (verified in server traces & main source)
Looking at the server trace spans and the current code on main:
-
Mid-turn workspace change triggers immediate session teardown:
WorktreeMcpService.performHandoff(apps/server/src/mcp/WorktreeMcpService.ts) dispatchesthread.metadata.update(bindingworktreePath) while the current turn is still active, which emitsprovider-session.detached("Workspace changed.") and schedulesProviderSessionManager.detach.
(Note: because the ACP child process is killed while still awaiting the/mcpHTTP tool response,WorktreeMcpService.performHandoffitself also getsInterruptedmid-flight beforesetupScriptRunnercompletes.) -
releaseEntryfails subscribers and concurrently closesentry.scope:
Inapps/server/src/orchestration-v2/ProviderSessionManager.ts(releaseEntry, lines 1251–1266 onmain), unlessgracefulSubscribers === true, it callsfailSubscribers(entry, "Workspace changed.", ...)(which causes Cursor'sProviderAdapterEventStreamErrorfailure) and immediately callscloseScopeWithin(entry.scope, ...)to tear down the session's Effect scope. -
InterruptescapesRunExecutionServicebeforewriteFinalRunEvents(why Antigravity hangs forever):
Inapps/server/src/orchestration-v2/RunExecutionService.ts(startRootRun→providerEventFiber, lines 1720–1780 onmain):Effect.catchCauseIf((cause) => !Cause.hasInterruptsOnly(cause), ...)(line 1720) catches theProviderAdapterEventStreamError.- Because
routing.rootProviderTurnId !== null && !routing.rootTurnEnded, it callsinput.session.interruptTurn({ providerThread, providerTurnId: routing.rootProviderTurnId, requestRuntimeRestart: true })(line 1736). - For
AcpAdapterV2,interruptTurnis scoped to the provider session (entry.scope). BecausereleaseEntryis simultaneously closingentry.scope,AcpAdapterV2.interruptTurnimmediately fails in ~0.1 ms withInterruptError: All fibers interrupted without error. - Critical bug at lines 1744–1751:
Because this handler filters out
Effect.catchCauseIf( (interruptCause) => !Cause.hasInterruptsOnly(interruptCause), (interruptCause) => Effect.logWarning(...).pipe(Effect.as(false)), )
Interrupt-only causes (!Cause.hasInterruptsOnly(interruptCause)), theInterruptfrominterruptTurnescapes uncaught out ofproviderEventFiber's outercatchCauseIfand abortsproviderEventFiberbeforewriteFinalRunEvents(line 1772) can run. - As a result, no terminal
run.updatedevent is ever written, the active run staysrunningforever in SQLite, and the queuedworktree-continuationremains blocked until manual Stop.
(Related: #35274 reports the same infinite running symptom for Grok (AcpAdapterV2) on main; #22971 tracks the Claude Workspace changed. failure. The trace below confirms the exact mechanism is AcpAdapterV2.interruptTurn exiting Interrupted and escaping RunExecutionService.ts:1744.)
Impact
Major degradation or frequent failure
Version or commit
T3 Code (Beta) 0.1.7 (322f6544dfad); root-cause lines verified still present on main (5ceabb3fe8f7)
Environment
macOS 26.5 (25F71, arm64), T3 Code (Beta) 0.1.7 Desktop, Antigravity (gemini-4-carbon) & Cursor (gemini-4-carbon)
Logs or stack traces
01:37:41.435Z | WorktreeMcpService.handoff | dur=3679.34ms | exit=Interrupted
01:37:41.435Z | WorktreeMcpService.performHandoff | dur=3678.98ms | exit=Interrupted
01:37:42.040Z | GitWorkflowService.createWorktree | dur=3035.08ms | exit=Success
01:37:45.082Z | ProviderSessionManager.detach | dur=80.65ms | exit=Success
01:37:45.084Z | AcpAdapterV2.interruptTurn | dur=0.11ms | exit=Interrupted
Excerpt from server.trace.ndjson (AcpAdapterV2.interruptTurn child of RunExecutionService.startRootRun at 01:37:45.084Z, secrets/paths redacted):
exit: {
_tag: "Interrupted",
cause: "InterruptError: All fibers interrupted without error
at AcpAdapterV2.interruptTurn (apps/server/dist/runtimeLayer.mjs)
at RunExecutionService.startRootRun
at ProviderTurnStartService.start
at OrchestrationEffectExecutorV2.execute"
}
Workaround
- Start threads directly in a worktree (
t3_thread_launchwithworkspaceStrategy) instead of handing off mid-turn. - If an Antigravity thread hangs in
runningright aftert3_worktree_handoffcreates the worktree, manually clicking Stop settles the stuck run and immediately unlocks the queued continuation.
Activity
juliusmarminge commentedon Nov 13, 2026
This is the same problem as #35274, so I'm closing it in favour of that one. If it is different, say how and it will be reopened.