[BUG] Windows: a subagent's background-task completion notification is queued but has no idle-wake consumer — the subagent hangs until something else gives it a turn (refs #78338, #21048, #29163)

Status Open
Reported on v2.1.258
Maintainer reply None cached
Activity 0 comments · opened Sep 2, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report (please file separate reports for different bugs)
  • [x] I am using the latest version of Claude Code

What's Wrong?

When a subagent starts a shell script with Bash(run_in_background: true) and then ends its turn,
the script's completion notification is created and queued, but nothing ever delivers it to the
subagent. The subagent stays idle indefinitely, and the session waiting on its report hangs.

The notification is not lost. It is queued immediately when the script exits, and it is delivered
correctly the moment the subagent happens to be in a turn — which in practice means after a human
notices the stall and nudges the agent by hand. There is simply no consumer that wakes an idle
subagent.

The identical mechanism works for the main session: its own background tasks are dequeued within
milliseconds and start a new turn.

Measured on 2.1.258 / Windows 11 across three instrumented runs in one session, from the
queue-operation records in the session transcript:

| Run | Task owner | Queued at (= script exit) | Left the queue at | How | Delay |
|---|---|---|---|---|---|
| A | subagent (idle) | 12:23:57.581 | 12:26:56.645 | remove / absorbed_mid_turn | 2m 59s, only after a manual nudge |
| B | subagent (idle) | 12:37:22.027 | 12:39:41.761 | remove / absorbed_mid_turn | 2m 20s, only after a manual nudge |
| C | subagent (kept active) | 12:50:37.514 | 12:51:06.325 | remove / absorbed_mid_turn | 29s, delivered on its own |
| control | main session | 12:25:03.403 | 12:25:03.410 | dequeue | 7 ms, woke the session |

Runs A and B: the subagent went idle before its script finished. The queued notification sat there
until a manual message gave the subagent a turn, and was then absorbed into that turn.

Run C: the same subagent shape, except the subagent was deliberately kept busy (eight sequential
20-second foreground calls) so that it was mid-turn when its script exited. The notification was
absorbed at the next tool-result boundary and the subagent did receive it — its own reasoning
for that step reads: *"I also received a task-notification that the background task from STEP 1
completed. That's interesting - it appears in my context as a system-reminder."* It then transcribed
the full <task-notification> block verbatim.

So the defect is precisely: the queue entry for a subagent-owned background task has no idle-wake
consumer.
absorbed_mid_turn is the only path it ever takes; the dequeue-and-start-a-turn path
that serves the main session never fires for it.

Two consequences worth noting:

  • The background shell is not killed when the subagent ends its turn (this is not #50572): in all

three runs the script wrote its exit timestamp to disk exactly 20s / 150s after its start
timestamp, as instructed.

  • The subagent is alive and fully resumable — any message wakes it and it continues correctly. What

recovers it is being given a turn, not the notification.

In day-to-day use (Agent Teams mode) this costs at least one stall a day, sometimes several. A
teammate stuck this way is indistinguishable from one still working, so the operator must first work
out which teammate to nudge.

What Should Happen?

A queued completion notification for a subagent-owned background task should wake that subagent and
start a turn, the way the main session's own notifications are dequeued within milliseconds.

Error Messages/Logs

No error is emitted anywhere; that is part of the problem. The queue records are the evidence:


2026-09-02T12:23:57.581Z  enqueue  bo82igvrj                        <- subagent's script exits
2026-09-02T12:25:03.403Z  enqueue  bkokitup5                        <- main session's control task
2026-09-02T12:25:03.410Z  dequeue  bkokitup5                        <- 7 ms: main session woken
2026-09-02T12:26:56.645Z  remove   bo82igvrj  absorbed_mid_turn     <- 2m59s: only after a nudge

Steps to Reproduce

  1. From the main session, spawn a named subagent whose prompt is exactly: start

bash -c 'date +%s > start.txt; sleep 20; date +%s > end.txt' with run_in_background: true;
then END the turn immediately, reporting one word. The prompt must explicitly forbid TaskOutput,
Monitor, sleeping and polling, or the measurement is destroyed.

  1. In parallel, from the main session, start a control task:

bash -c 'sleep 105; date +%s > control_end.txt' with run_in_background: true.

  1. Wait. The main session is woken by its control task. The subagent is not woken by its own.
  2. Inspect the session transcript for "type":"queue-operation" records. The subagent's task shows

enqueue at the script's exit time and nothing after it; the main session's task shows
enqueue immediately followed by dequeue.

  1. Send the subagent any message. A remove with "reason":"absorbed_mid_turn" appears for its

task at that moment, and the notification surfaces in the UI under the subagent.

To see the delivery path working (run C above), repeat with a 150s script and give the subagent a
turn while the script is still running — e.g. instruct it, on being messaged, to make eight
sequential bash -c 'sleep 20; date +%s' calls. The notification arrives mid-turn on its own.

Claude Model

Not sure / Multiple models

Is this a regression?

No, this never worked

Last Working Version

_No response_

Claude Code Version

2.1.258

Platform

Anthropic API

Operating System

Windows

Terminal/Shell

Windows Terminal

Additional Information

This appears to be #78338's mechanism, measured on Windows in the subagent path. #78338 (Linux,
closed) describes the notification as a passively queued command with no idle-wake consumer, so a
long-idle parent stays unwoken. The queue-operation records above are a direct observation of
exactly that, plus the contrast with the working dequeue path in the same session and second.
Please consider reopening it rather than closing this as a duplicate of it.

Also related:

  • #21048 — Windows, run_in_background completion notification does not appear and does not wake

Claude from idle. Reported 2026-01-26 on 2.1.19 with has repro, marked stale, then closed as
not planned with no maintainer response. Same platform, same symptom, main-agent variant. The runs
above find the main-session path working on 2.1.258, so if #21048 is still live it is now a
narrower case than this one.

  • #29163 — team agents go idle without responding; closed as duplicate, macOS. There SendMessage did

not revive the agents; here any message does, which localises this to the wake path only.

  • #75043 — open, reproduced, macOS: nested subagents, child completion notifications delivered to

the wrong parent. Note the queue entry here also carries the main session's sessionId for a
task owned by a subagent, which may be the same ownership confusion.

  • #29271, #24108, #47930, #85047 — the surrounding Agent Teams idle-notification cluster.

Methodological caution for anyone reproducing this. Do not diagnose it by asking the subagent
what woke it. In run A the nudge I sent happened to contain the phrase "background-task completion
notification"; the woken subagent then asserted the notification had arrived with the message, which
was not true at that point. Absence from the subagent's JSONL transcript is also not evidence:
notifications delivered via absorbed_mid_turn are not persisted as separate transcript entries at
all, in the main session either. Only the queue-operation records, the on-disk script timestamps,
and a subagent that is instructed to transcribe its context verbatim are load-bearing.

View original on GitHub ↗