Skip to content

[Bug]: Agents panel keeps a finished Claude subagent as running, or interrupted, after the thread's process restarts #14802

Closed as not planned

Description

@caitlon

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 Claude thread, have the main agent start background subagents (Agent tool, run_in_background) whose work takes several minutes.
  2. While they run, restart the thread's Claude process. In our case this happened when the model was switched in the composer's model picker; a provider crash or --resume should do the same.
  3. Let the subagents finish after the restart, then look at the Agents panel.

Expected behavior

Each row shows the subagent's real final state: completed, with the duration it actually ran.

Actual behavior

Two subagents of the same type were affected in one thread. Times are UTC, taken from the subagents' own transcripts (~/.claude/projects/<project>/<session>/subagents/agent-*.jsonl):

subagent started finished (last assistant text) panel at 09:33
A 09:00:04 09:05:58 grey, "Background agent didn't finish before the previous…"
B 09:04:19 09:11:37 blue, still working, "28m 57s", last tool Bash

Both completed: each transcript ends with the subagent's final text, and the main agent received both results ("finished after the restart" in its own summary). Twenty-two minutes after B finished, the panel still showed it as working with a running timer, and A as interrupted. Every other subagent in the thread that did not overlap the restart was shown correctly.

So completion of a subagent that outlives its parent process is never applied to its row: the row either stays on the state recorded before the restart or keeps running. This differs from #14002, which covers a subagent continued with SendMessage; here nothing was resumed, only the parent process restarted.

Impact

Minor bug or occasional failure

Version or commit

Desktop 0.0.44

Environment

macOS 27, T3 Code desktop 0.0.44, Claude Code 2.1.286, Claude provider (Fable 5.1 session).

Workaround

None in the panel. The subagent's transcript, or the main agent's own report, shows the real state.

Related

The model and effort shown on every row are the parent session's, not the subagent's (same thread: rows said medium while the transcripts record high, xhigh and low). That is #7281, closed with #13333 unmerged during the V2 freeze, so it is not repeated here.

Activity

  1. juliusmarminge commented on Oct 2, 2026

    @juliusmarminge
    Member

    Note

    Grok responding on behalf of Julius.

    Triage

    Thanks for the detailed timeline, @caitlon. The transcript timestamps made this easy to trace. It's a real Agents panel bug on current main (54084ae), and you're right that it's separate from open issue #14002.

    Why the restart happens: switching the model in the composer restarts Claude for claudeAgent and keeps the resume cursor (shouldRestartForModelSelectionChange in ProviderCommandReactor). A crash or --resume goes down the same path.

    Subagent A (grey, interrupted): on shutdown, stopSessionInternal writes task.completed with status: "stopped" for every task that's still live. The resumed CLI then reports orphaned tasks with reason: "worker_restart", also as stopped. ClaudeAdapter forwards the status but drops the reason. The panel fold maps stopped to interrupted, and once a row is terminal, a later task.completed only fills in a missing result or usage. It never changes the status or completedAt. So the real completion never replaces the stop.

    Subagent B (blue, still running): this row never got a terminal event that the fold kept. The new process starts with an empty live-task set, so the shutdown sweep doesn't cover it. background_tasks_changed is the roster snapshot the SDK says hosts should reconcile with after a CLI restart, but T3 currently ignores it on purpose. So nothing ever corrects the missing bookend. The 28m 57s timer counts from the original 09:04 start, which matches what you saw.

    How this differs from the open PRs:

    Likely fix: keep reason: "worker_restart" and don't treat a restart-time stopped as final, so a later completed or failed for the same task can set the status, completedAt, and summary. Also reconcile background_tasks_changed after the new process starts so a missed completion can't leave a timer running.

    There's no workaround in the panel yet. As you noted, the subagent transcript or the main agent's report shows the real result.

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

    @navidnadali

    Reproduced on main (54084ae) in an isolated dev server with Claude Code 2.1.287:

    • A model switch restarts the Claude process. T3's shutdown sweep writes stopped for the live subagents. The resumed CLI then reports each orphan again as stopped, with "Background agent … didn't finish before the previous session ended". That notification carries no reason and no tool_use_id, so keying on worker_restart wouldn't catch this path.
    • The orphaned subagents don't continue on their own. They finish only when the parent resumes them with SendMessage. That emits another task_started for the same task under the SendMessage call's tool_use_id, which is the [Bug]: A Claude subagent resumed with SendMessage stays "completed" or "failed" in the Agents panel (regression of #5529) #14002 mechanism.
    • On main, both rows stay grey "Stopped" after the subagents finish ("alpha done", "beta done").

    #14696 settles both rows as completed, run 2, with their real result and duration. I've added a regression test with these exact rows, plus before/after captures and a recording, to that PR.

    I couldn't reproduce subagent B, the row that keeps running. In every run, the sweep and the orphan notification settled it. @caitlon, if you still have ~/.t3/userdata/logs/provider/events.<threadId>.log for that thread, B's rows around the restart would show which bookend went missing.

    @juliusmarminge, would you be OK merging #14696 for #14002 and for subagent A here, and keeping this issue open for B? #14696 has passed triage and Macroscope approved it. Its CI workflows are waiting for approval to run, since it comes from a fork.

  4. caitlon commented on Oct 2, 2026

    @caitlon
    Author

    Thanks for digging in, @navidnadali. I still have the provider log for that thread (events.f43327d0-….log, desktop 0.0.44). Here are the canonical task events for the two rows. Times are UTC, and I trimmed the summaries:

    09:03:54.683  session.started                                   (process restarted after the model switch)
    09:03:56.759  task.completed  ae57307fc89a2aa86  stopped        Background agent "Gemini check: code and consumers" ...   <- A
    09:04:11.936  task.started    af505255719175812                 Gemini check: code and consumers                          <- B
    09:05:58.605  task.updated    ae57307fc89a2aa86  completed
    09:05:58.605  task.completed  ae57307fc89a2aa86  completed      Angle: code path and every consumer ...                   <- A
    09:11:37.851  task.updated    af505255719175812  completed
    09:11:37.854  task.completed  af505255719175812  completed      Angle: code path and every consumer ...                   <- B
    

    Two things in it differ from your repro:

    • A finished on its own. After the restart's stopped, A got a real completed at 09:05:58. No SendMessage and no second task_started came in between. So in this run the orphan did continue without being resumed, and the late completed was the only event that could have settled the row. fix(client-runtime): a resumed Claude subagent no longer stays failed or stopped in the Agents panel #14696 may not cover A if it keys on a new SendMessage tool use.
    • B was not orphaned. It started 17 seconds after the restart, and both bookends are in the log: task.started at 09:04:11 and task.completed with status completed at 09:11:37. At 09:33 the panel still showed it as working, with the timer counting from 09:04. So no event was missing. The completion was in the provider log and never reached the row.

    A setup detail that may explain B: on this machine two T3 servers were running against the same ~/.t3/userdata at the time, the desktop app's backend and a t3 serve background service. That is the condition in #14115, where each server runs its own provider session for the same thread. If the client was attached to the server that did not own this session, its projection would never see B's completed, which would also explain why you can't reproduce B with a single server. I haven't confirmed which server the window was attached to.

    I can share more lines from this log if you need them. I'd rather not attach the whole file, because it contains the full conversation.

  5. juliusmarminge commented on Oct 2, 2026

    @juliusmarminge
    Member

    Thanks for the detailed timelines and the additional log excerpt. They make the two cases much clearer.

    The orchestrator V2 rewrite has now landed in #2829. It removes the Agents panel and the V1 provider/status-folding paths investigated in this report. Subagent state is now shown through Lineage and the V2 projections, so I am closing this as an obsolete V1 report. Our earlier cleanup missed this one.

    This does not establish that every restart or multi-server status problem is fixed. If you see the same symptom on a build containing V2, please open a fresh issue with the build, what Lineage shows, and whether multiple servers share the same data directory. Please link this report so the timelines and the distinction between A and B are preserved. A small, redacted log excerpt like the one above is enough; there is no need to share the full conversation.

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