You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[Bug]: Nested Claude subagents stay Running in the UI after their parent subagent hits the usage limit, while the thread list reports them idle #19993
I searched existing issues and did not find a duplicate.
I included enough detail to reproduce or investigate the problem.
Area
Not sure
Steps to reproduce
Observed once on 2026-10-15. Not yet reproduced on purpose.
In a Claude thread, the root agent launches a native Claude subagent (Agent tool) as a worker.
The worker launches two native subagents of its own (two review agents, so spawn depth 2).
About 9 seconds after the two review agents start, the worker hits its Claude session usage limit and stops.
Look at the Lineage panel, the subagent group in the transcript, and the composer.
Expected behavior
When a subagent's parent stops (on a session limit or for any other reason) and the subagent ends, the UI shows the subagent as stopped or idle, matching what the thread list reports. The "Waiting on N subagents" bar clears.
Actual behavior
T3's own thread list and its UI disagree about the two review agents.
t3_thread_list (MCP tool, includeSubagents: true) reports both review agents with status idle, latestRunId: null, and updatedAt 9 seconds after createdAt.
The Lineage panel shows "2 running", with both agents at 1.1h and the timers still counting.
The subagent group in the transcript shows "2 working", with each agent marked "Running".
The composer shows "Waiting on 2 subagents ... Stop".
Neither the root agent nor the worker could stop them. Claude Code's TaskStop returned "No task found" for their IDs, and the worker held no IDs for them.
A guess at the cause, not verified: the worker ended before the review agents' finish events reached T3, so the UI never received a terminal status for them.
Related reports with the same symptom and a different trigger: #19440 (Claude process exits while the parent is idle), #16355 (nested subagent completes during a user turn), #18910 (completion arrives but is not applied), #17847 (stopped notification after the session ended). Here the trigger is a parent subagent stopped by a usage limit while its own subagents had just started.
Impact
Minor bug or occasional failure
Version or commit
T3 Code (Nightly) 0.0.46-nightly.20261014.3118
Environment
macOS 27.0.1, desktop app, Claude provider, Claude Code 2.1.300
Logs or stack traces
No response
Screenshots, recordings, or supporting files
Screenshots of the Lineage panel, the transcript subagent group and the composer bar are available on request.
Thanks for the detailed report. I checked it against the related issues before deciding where it belongs.
Why this isn't a duplicate of #19440 / #19464: that fix settles background agents when the Claude CLI process exits. On main, a rejected rate_limit_event is handled as a pause ("Rejected windows pause the SDK without ending its turn"), so a usage limit by itself shouldn't trigger that process-exit cleanup. #16355 and #18910 are about a completion that does arrive; here it looks like the review agents' end never arrived at all.
What the code shows: subagents started by another subagent (spawn depth > 1) are tracked separately, and their end is reported by Claude to the subagent that started them, not to the root. I didn't find anything that marks those depth-2 subagents as ended when their owning subagent stops before reporting their end. That fits what you saw, but this was seen once and not reproduced, so I can't confirm that path yet.
To move this forward, could you:
Share the server log for that thread around the time the worker hit the limit (the task_started / task_notification events for the two review agents, and whether the worker's own task got a terminal notification).
Second reproduction on 2026-10-15. It adds three things: the stuck child was itself rate-limited and then resumed through Claude Code's SendMessage, the UI Stop button cannot clear the stale "running" entry, and T3's own API says the child never had a run. The depth-1 parent stayed alive throughout, so this case does not fit the guess in the issue body.
Steps
The root thread launches a native subagent (Opus, Agent tool, background).
That subagent launches three Sonnet subagents in parallel (spawn depth 2), titled "Worker 1" to "Worker 3".
At 13:42 UTC all three hit the session limit (HTTP 429, rate_limit) right after their first prompt.
After the reset, the depth-1 subagent resumes each worker with SendMessage, which keeps the same agent ID.
All three finish in Claude Code. Worker 3's transcript (subagents/agent-<id>.jsonl) ends with its final message at 18:00:04 UTC, and its parent acts on the completion.
Observed state for Worker 3
t3_thread_read: status: "idle", runCount: 0, latestRunId: null, activeRunId: null, itemCount: 3, updatedAt 17:46:25 UTC. The items are the prompt, "You've hit your session limit", and "Agent terminated early due to an API error ... rate_limit". Nothing from the resumed run.
Lineage: "1 running" for 1.3h and counting.
Composer: "Waiting on subagent Worker 3: full test suite after rebase" with Stop.
Clicking Stop does nothing. t3_thread_interrupt returns {"runId":null,"status":"no_active_run"}.
Expected
Either the resumed run's items and completion land in the child thread, or Stop clears a "running" entry whose child thread has no active run.
Open question
Workers 1 and 2 took the same path and do not show as running. I don't know why only Worker 3 is stuck. Two differences, neither confirmed as the cause: it finished at 18:00 UTC, between the other two (17:49 and 18:07 UTC), and Worker 3's parent was blocked in a long foreground Bash call when its completion arrived.
Third reproduction on 2026-10-15, in a separate thread with the same app, project and Claude account. It rules out rate limits, resume and spawn depth 2 as required conditions, and the parent never stopped first.
Setup
The root session spawned one Sonnet subagent with Claude Code's Agent tool, in the background, at spawn depth 1. Its transcript has no rate_limit or API error entries. It was never resumed with SendMessage.
Timeline (UTC)
17:45:59 the subagent starts.
17:49:47 its last Bash call, an rm cleanup and a rerun.
17:54:13 df -h / reports the root volume 100% full, 117 MiB free. The transcript ends with an API request at that second and no response.
17:54:41 the root session receives <task-notification> with <status>completed</status>, summary Agent "Run title-gap check matrix" finished. It kept writing until at least 18:24.
Observed state
t3_thread_list for the child: status: "idle", latestRunId: null, itemCount: 12, updatedAt 17:54:05, 36 s before the parent got the completion.
The child thread shows "Working for 1h 23m 24s" with "Running rm" as its last item. Stop does nothing.
Confound
The disk was full when the subagent ended. Its own final message never reached its transcript, and T3 may have failed to persist the end event for the same reason. Free space has since recovered to 96 GiB. I can't say whether the disk caused this.
Your questions
Question 2: the Claude processes stayed up here.
Screenshots of all three stuck entries are saved. I'll attach them from the browser.
I can send the server log for these windows if you tell me where T3 writes it.
I traced the nested path on main (8653c8f) and have a failing adapter test for one piece of it.
What happens while the root turn is idle. A depth-2 task_started that arrives with no active root turn is buffered for the next wake turn (ClaudeAdapterV2.ts, idle branch around L6517-6560). While a start for that task is buffered, its task_notification is also deferred (canApplyOutcome requires !hasBufferedStart, from #18778). Nested notifications never open a continuation, so the deferred outcome is applied only when something else wakes the root, normally the owning subagent's own completion. Until then, the worker's state doesn't move.
The test: the root goes idle with a background depth-1 owner. The owner launches a depth-2 worker, which finishes, returns its tool result, and the owner keeps working. No subagent.updated is emitted for the worker at all. The existing test "keeps a nested subagent's launch in order while the root turn is idle" covers the later replay, once the owner finishes and wakes the root.
How this could fit the second report. Worker 3 was shown and then got stuck, which points to a resume rather than a first launch. A SendMessage resume emits a fresh task_started. If that arrived while the root was idle, it was buffered, and the worker's completion was deferred behind it. If the wake that should replay it never happened (for example the jammed continuation gate in #20430), the entry stays "running". I haven't reproduced the resume variant itself, so treat that as a hypothesis.
Possible fix. For a nested task, apply the buffered start and the outcome immediately in the idle branch, since no wake turn will replay them on its own. Happy to send that with the test if this direction looks right.
Sent by Ravdeep's agent: Claude Opus 5.5 in Claude Code, running in T3 Code.
Activity
juliusmarminge commentedon Oct 15, 2026
Note
Grok responding on behalf of Julius.
Thanks for the detailed report. I checked it against the related issues before deciding where it belongs.
Why this isn't a duplicate of #19440 / #19464: that fix settles background agents when the Claude CLI process exits. On main, a rejected
rate_limit_eventis handled as a pause ("Rejected windows pause the SDK without ending its turn"), so a usage limit by itself shouldn't trigger that process-exit cleanup. #16355 and #18910 are about a completion that does arrive; here it looks like the review agents' end never arrived at all.What the code shows: subagents started by another subagent (spawn depth > 1) are tracked separately, and their end is reported by Claude to the subagent that started them, not to the root. I didn't find anything that marks those depth-2 subagents as ended when their owning subagent stops before reporting their end. That fits what you saw, but this was seen once and not reproduced, so I can't confirm that path yet.
To move this forward, could you:
task_started/task_notificationevents for the two review agents, and whether the worker's own task got a terminal notification).UkrainianCitizen commentedon Oct 15, 2026
Second reproduction on 2026-10-15. It adds three things: the stuck child was itself rate-limited and then resumed through Claude Code's
SendMessage, the UI Stop button cannot clear the stale "running" entry, and T3's own API says the child never had a run. The depth-1 parent stayed alive throughout, so this case does not fit the guess in the issue body.Steps
Agenttool, background).rate_limit) right after their first prompt.SendMessage, which keeps the same agent ID.subagents/agent-<id>.jsonl) ends with its final message at 18:00:04 UTC, and its parent acts on the completion.Observed state for Worker 3
t3_thread_read:status: "idle",runCount: 0,latestRunId: null,activeRunId: null,itemCount: 3,updatedAt17:46:25 UTC. The items are the prompt, "You've hit your session limit", and "Agent terminated early due to an API error ... rate_limit". Nothing from the resumed run.t3_thread_interruptreturns{"runId":null,"status":"no_active_run"}.Expected
Either the resumed run's items and completion land in the child thread, or Stop clears a "running" entry whose child thread has no active run.
Open question
Workers 1 and 2 took the same path and do not show as running. I don't know why only Worker 3 is stuck. Two differences, neither confirmed as the cause: it finished at 18:00 UTC, between the other two (17:49 and 18:07 UTC), and Worker 3's parent was blocked in a long foreground Bash call when its completion arrived.
Screenshots are available on request.
UkrainianCitizen commentedon Oct 15, 2026
Third reproduction on 2026-10-15, in a separate thread with the same app, project and Claude account. It rules out rate limits, resume and spawn depth 2 as required conditions, and the parent never stopped first.
Setup
The root session spawned one Sonnet subagent with Claude Code's
Agenttool, in the background, at spawn depth 1. Its transcript has norate_limitor API error entries. It was never resumed withSendMessage.Timeline (UTC)
rmcleanup and a rerun.df -h /reports the root volume 100% full, 117 MiB free. The transcript ends with an API request at that second and no response.<task-notification>with<status>completed</status>, summaryAgent "Run title-gap check matrix" finished. It kept writing until at least 18:24.Observed state
t3_thread_listfor the child:status: "idle",latestRunId: null,itemCount: 12,updatedAt17:54:05, 36 s before the parent got the completion.Confound
The disk was full when the subagent ended. Its own final message never reached its transcript, and T3 may have failed to persist the end event for the same reason. Free space has since recovered to 96 GiB. I can't say whether the disk caused this.
Your questions
voida6 commentedon Oct 17, 2026
I traced the nested path on
main(8653c8f) and have a failing adapter test for one piece of it.What happens while the root turn is idle. A depth-2
task_startedthat arrives with no active root turn is buffered for the next wake turn (ClaudeAdapterV2.ts, idle branch around L6517-6560). While a start for that task is buffered, itstask_notificationis also deferred (canApplyOutcomerequires!hasBufferedStart, from #18778). Nested notifications never open a continuation, so the deferred outcome is applied only when something else wakes the root, normally the owning subagent's own completion. Until then, the worker's state doesn't move.The test: the root goes idle with a background depth-1 owner. The owner launches a depth-2 worker, which finishes, returns its tool result, and the owner keeps working. No
subagent.updatedis emitted for the worker at all. The existing test "keeps a nested subagent's launch in order while the root turn is idle" covers the later replay, once the owner finishes and wakes the root.How this could fit the second report. Worker 3 was shown and then got stuck, which points to a resume rather than a first launch. A
SendMessageresume emits a freshtask_started. If that arrived while the root was idle, it was buffered, and the worker's completion was deferred behind it. If the wake that should replay it never happened (for example the jammed continuation gate in #20430), the entry stays "running". I haven't reproduced the resume variant itself, so treat that as a hypothesis.Already covered elsewhere:
no_active_run): fix(server): Stop clears native subagents whose runtime is gone #19544Neither touches the idle nested deferral.
Possible fix. For a nested task, apply the buffered start and the outcome immediately in the idle branch, since no wake turn will replay them on its own. Happy to send that with the test if this direction looks right.
Sent by Ravdeep's agent: Claude Opus 5.5 in Claude Code, running in T3 Code.