Skip to content

[Bug]: Stale "Waiting on background task T3 Worktree Handoff" banner persists after a Claude worktree handoff #15993

Description

@letrandat

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

  1. In a top-level claudeAgent / claude-opus-5-5 thread (full access), have the agent call t3_worktree_handoff with a continuationPrompt (startFromOrigin: true, runSetupScript: false).
  2. Let the thread continue. The worktree is created, the thread is rebound, and later turns run in the worktree.
  3. Finish several more turns, then look at the composer once the thread is idle.

Expected behavior

Once the handoff's turn ends, its tool item is settled, and the composer shows no pending work after later turns complete.

Actual behavior

The composer keeps showing "Waiting on background task T3 Worktree Handoff" with a Stop button, after 7 later turns that all completed normally. The agent has nothing running. When asked what it was waiting for, it confirmed the handoff had finished long before.

From the thread's projection (read from a copy of the state DB):

Run Status Note
1 failed "The provider event stream closed unexpectedly…" about 1.4 s after the handoff tool_use
2 cancelled the handoff continuation
3–8 completed normal turns inside the worktree

The dynamic_tool turn item for mcp__t3-code__t3_worktree_handoff in run 1 is still status: "running" with completedAt: null. Nothing will ever complete it, because the Claude session that owned it was released by the workspace-change detach.

Two pieces combine:

  • When a run reaches its final status, RunExecutionService closes open run-owned subagent rows (L687), but deliberately leaves dynamic_tool and command_execution items open so a late completion can arrive (L93-L101). That holds while the provider process is alive. Here the session was released, so the item stays running forever.
  • pendingBackgroundTurnItems (L178-L195) lists any active background-type item from any run that is not rolled_back, so the orphan from failed run 1 shows up again every time a later run settles.

This is related to #15136, which has the same trigger: the planned detach on handoff is treated as an unexpected stream close for Claude. There, the handoff item ended cancelled and the continuation stayed held. Here, the continuation was cancelled, later turns ran fine, and the handoff item was never settled. That suggests the item cleanup on detach is racy, and #15203 may not cover it because it changes how the detach ends the turn, not what happens to in-flight tool items. The same leftover probably appears whenever a session is released while a tool item is in flight. A quick scan of the same DB found 3 other threads with command_execution items still running from older runs.

Pressing Stop is the only way out, and it targets work that no longer exists.

Impact

Minor bug or occasional failure

Version or commit

0.0.46-nightly.20261004.2657

Environment

macOS, desktop app, local server, claudeAgent / claude-opus-5-5, full access

Logs or stack traces

run 1  failed     error item: "The provider event stream closed unexpectedly. Retry the turn; if it keeps failing, check the provider and server logs."
item   dynamic_tool  toolName=mcp__t3-code__t3_worktree_handoff  title="T3 Worktree Handoff"  status=running  completedAt=null

Filed by Claude Opus 5.5, running in T3 Code through the Claude Code harness, on behalf of @letrandat.

Activity

  1. juliusmarminge commented on Oct 5, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks for the thorough write-up, @letrandat. Your projection snapshot matches current main (cf3e714b0f), and 0.0.46-nightly.20261004.2657 isn't missing a fix.

    What I found

    t3_worktree_handoff rebinds the thread and schedules provider-session.detach. Claude sessions are exclusive, so that detach releases the whole session. releaseEntry fails every event subscriber with ProviderAdapterEventStreamError before it closes the adapter, and the run is stored as failed with "The provider event stream closed unexpectedly…".

    finalizeActiveTurn does cancel open tool calls, but it runs while the session scope is closing, after those subscribers are gone, so the cancellation never reaches the run. Run finalization only closes open subagent rows, so dynamic_tool and command_execution items stay running.

    A later run doesn't adopt them either. Inheritance requires the same provider thread, and the released Claude session no longer exists. Meanwhile pendingBackgroundTurnItems still lists any active command, dynamic tool, or subagent whose run isn't rolled_back. So once a later turn settles, the composer shows Waiting on background task … for the handoff item. Stop works from the same list and marks items on a dead provider session as interrupted, which is why it clears the banner even though nothing is running.

    The two outcomes depend on timing. If the Claude process exits first, finalizeActiveTurn can publish the cancellation while subscribers are still attached, and the item ends cancelled (what #15136 recorded). If the detach releases the session first, the cancellation is dropped and the item stays running, which is what you're seeing. The same leftover can happen whenever an exclusive session is released while a command or dynamic tool is still running.

    #15136 is the same detach recorded as an unexpected stream close. Open PR #15203 turns a planned workspace detach into an interruption so the continuation can start, but it leaves in-flight dynamic_tool and command_execution rows alone, so this banner could still appear with that change.

    Workaround: press Stop on the banner. That settles the leftover items on the dead session, though it doesn't revive the handoff.

    Likely fix area

    • RunExecutionService / run finalization. One option is to terminalize open dynamic_tool and command_execution rows when a run settles, the same way subagent rows are handled.
    • releaseEntry / finalizeActiveTurn ordering. Another option is to publish the tool cancellations before failing subscribers on an exclusive-session release.
    • packages/shared/src/orchestrationV2PendingBackgroundWork.ts (pendingBackgroundTurnItems). A third option is to skip items whose provider session is already gone.

    A maintainer will decide on the fix direction.

  2. added
    bugSomething is broken or behaving incorrectly.
    via-triageFiled through npx t3 triage
    on Oct 5, 2026
  3. LetterXbox commented on Oct 8, 2026

    @LetterXbox

    Additional reproduction on macOS desktop connected to a remote Linux server (0.0.46-nightly.20261007.2774), using Claude Sonnet 5.5 in Full access mode.

    The same stale-task pattern occurs, but the suggested Stop workaround does not clear it:

    • The composer shows Waiting on 2 background tasks: advisor, mcp__t3-code__t3_worktree_handoff.
    • Thread activity records both as dynamic_tool items still marked running.
    • Run 3 failed with "The provider event stream closed unexpectedly." The handoff continuation (run 4) was cancelled; runs 5–8 subsequently completed. The thread has no active run, but those two tool items remain pending.
    • Clicking Stop briefly changes the button to Stopping..., then it returns to Stop with both tasks still listed. This was reproduced directly in the macOS UI.

    The worktree handoff did take effect and later turns ran there, so this appears to be stale tool state after the failed handoff. The additional issue is that Stop fails to settle the leftover items in this case.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or behaving incorrectly.via-triageFiled through npx t3 triage

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions