[Bug] Subagents not awaiting nested subagent results, causing duplicate work and race conditions
Status Closed — not planned
Reported on v2.1.183
Maintainer reply None cached
Activity 7 comments · opened Jun 21, 2026 · closed Aug 25, 2026
Bug Description
subagents dont await the results of the nested subagents they spawn. They even hallucinate/fabricate task notifications of subagents that they just spawned and then they proceed anyways or sometimes even do the work of the nested subagent that is running in the background. It's an ABSOLUTE mess of concurrent agents doing the same thing.
Environment Info
- Platform: darwin
- Terminal: cursor
- Version: 2.1.183
- Feedback ID: 319fcc41-9efc-41af-9f62-dc74a03f98fa
Errors
[]Showing cached comments. Read the full discussion on GitHub ↗
6 Comments
Found 3 possible duplicate issues:
This issue will be automatically closed as a duplicate in 3 days.
🤖 Generated with Claude Code
Similar issue #69827, it consumed all my 5-hour limit in minutes.
I inspected the Claude Code source and I think the key is the following env-var:
This is not set by default, which means claude code ALWAYS badkgrounds subagents for some stupid reason. That is what causes havoc in nested subagents (but also for multiple regular subagents)
Important: You have to set it in your shell environment! Do not set it in the settings.json as the env vars in there won't be evaluated for the claude code session itself!
This needs a hard parent/child lifecycle invariant, not only a prompt fix.
Suggested invariant:
in_flightuntil a real terminal event is recordedcompleted,failed,cancelled,timed_out, andunknown_lostThe regression test should include a nested child that sleeps or blocks, then assert the parent does not fabricate a completion notification and does not duplicate the child task. The bad state here is "no error, but parent proceeds"; that should be observable as a lifecycle violation.
---
_Generated with ax._
Corroborating with a clean repro from today (Claude Desktop 1.18286.0, embedded Claude Code engine 2.1.197, macOS) — three separate instances in one session, all following the same shape:
A top-level orchestrator dispatched a
general-purposesubagent to investigate a topic directly. That subagent, instead of doing the work itself, calledAgent(..., run_in_background: true)to spawn its own nested background agent, then reported back to the orchestrator that it was "waiting for a background investigation agent" / "an investigation was running in the background" — and stopped there. There was no such agent from the orchestrator's perspective; the subagent had spawned it itself and then had no way to await it.Notably this isn't hallucination in the usual sense — the subagent's
Agenttool call genuinely returned "Async agent launched successfully... you will be notified automatically when it completes... say the agent is still running" and the subagent followed that literally. The bug is structural: a one-shot, non-persistent subagent invocation has no mechanism to receive a later notification, so following the tool's own guidance produces exactly this misreport. The orchestrator had to manually re-dispatch each investigation with explicit "you are the one who must do this directly, right now, do not spawn sub-agents, do not wait for anything."This lines up with
Necmttn's proposed invariant above — the missing piece here specifically is that a child'sin_flightstate needs to be scoped to something that can actually still act on the terminal event; an ephemeral subagent shouldn't be allowed to leave a child dangling in a state only a persistent ancestor could resolve. Also cross-referencing #69212, which looks like the routing side of the same mechanism (nested completions landing at the root rather than an ancestor able to act on them) — the orphaned grandchildren from these three repros are consistent with that routing failure.Stronger follow-up evidence from a second repro today (same environment: Claude Desktop 1.18286.0, embedded engine 2.1.197, macOS), this time confirmed directly on disk.
One top-level fact-check dispatch ("Verify external technical facts in heimdall spec") recursively fanned out into 22 subagent transcripts, 5 spawn-levels deep (per
spawnDepthin each.meta.json). Most strikingly, two of the depth-2 children are self-documenting instances of exactly the "not awaiting nested results" failure this issue describes:"noop""Placeholder while awaiting background agents"i.e., an agent spawned a nested background agent, had no way to actually wait for it to finish (no persistent context to receive the later notification), and rather than doing the work itself or failing loudly, it fabricated a placeholder/no-op result and returned. Multiple deeper descendants (depth 3–5) then independently re-researched the same handful of claims (Secret Service headless reliability, Windows Credential Manager, macOS Keychain silent access each researched twice by different branches) — consistent with duplicate work happening because siblings couldn't see each other's in-flight status, matching the "duplicate work and race conditions" in the title here.
One data point worth adding for anyone tracking cost impact: the orphaned descendants don't run forever once the routing failure happens — checked file mtimes vs. wall clock, the newest of the 22 transcripts had been idle ~1h50m with no further writes, all cleanly terminated. So it's wasted tokens from the initial uncontrolled fan-out plus a misleading UI, not an open-ended runaway bill — but the fan-out itself (1 call → 22 agents) is still a real, measurable cost multiplier before it stalls.
Cross-posted the same evidence to #69212 since the placeholder/noop behavior looks like the direct consequence of that routing gap.