[BUG] Subagent Termination Bug in Claude Code v1.0.62
Subagent Termination Bug in Claude Code v1.0.62
<human>
The subagent termination bug in Claude Code v1.0.89 has severely degraded the product's reliability, making the CLI completely unusable for long-running tasks requiring multiple agents—a critical capability I depend on daily for complex development workflows. This regression has forced me to switch to more reliable alternatives like Augment Code + Copilot, Cursor + Kilo Code, which handle parallel tool execution and multi-agent coordination far more consistently with the Sonic model. I'm particularly frustrated that previously functional prompts for launching multiple subagents (such as "immediately launch ten subagents in parallel with the task tool to complete your remaining todos") now fail consistently, and I couldn't identify the specific code changes causing this breaking behavior. I'd appreciate insight into the cause of this regression and whether a fix or workaround is planned, as the current state renders Claude Code unusable for my typical workflow needs.
</human>
Environment
- Platform (select one):
- [x] Anthropic API
- [ ] AWS Bedrock
- [ ] Google Vertex AI
- [ ] Other: <!-- specify -->
- Claude CLI version: v1.0.89
- Operating System: macOS (confirmed on multiple systems)
- Terminal: Various (iTerm2, Terminal App, etc.)
Bug Description
Multiple subagents launched via the Task tool work initially but are all terminated simultaneously when any single subagent encounters an API error or rate limit (HTTP 429). This is a regression from earlier versions where subagents had individual error handling.
Steps to Reproduce
- Launch multiple subagents using the Task tool (e.g., 3-5 parallel agents)
- Provide tasks that involve API-heavy operations (file searches, code analysis, etc.)
- Wait for subagents to begin working successfully
- Continue operation until one subagent hits a rate limit or API error
- Observe that ALL active subagents are immediately terminated
Expected Behavior
- Individual subagents should handle their own errors gracefully
- Rate limiting should only affect the specific subagent that hit the limit
- Other subagents should continue working independently
- Only user-initiated cancellation should terminate all subagents
- API errors should trigger retry logic, not termination
Actual Behavior
- All subagents are killed simultaneously when any single agent encounters an API error
- No graceful error handling or retry attempts
- Complete loss of work from all active subagents
- Cascade termination occurs regardless of error type (rate limits, network issues, etc.)
Root Cause Analysis
Based on code analysis of v1.0.89 compared to earlier versions:
Technical Details
- Shared AbortController: All subagents listen to the same
AbortController.signal - Cascade Termination: API errors trigger
abortController.abort()globally - Immediate Cleanup:
child.kill("SIGTERM")terminates all processes on abort signal - No Error Isolation: Individual subagent errors propagate to shared signal
Code Evidence
// Problematic pattern in v1.0.89
const cleanup = () => {
if (!child.killed) {
child.kill("SIGTERM"); // Kills ALL subagents
}
};
abortController.signal.addEventListener("abort", cleanup);
// Rate limit handling triggers global abort
if (status === 429) {
abortController.abort(); // Terminates entire subagent pool
}
Regression Timeline
- v1.0.61 and earlier: Individual subagent error handling ✅
- v1.0.85/v1.0.89: Introduced shared AbortController architecture ❌
- Impact: Broke multi-subagent workflows that previously worked reliably
Workarounds
- Use fewer parallel subagents (1-2 instead of 3-5+)
- Add delays between subagent launches to reduce rate limit probability
- Downgrade to v1.0.61 for critical multi-subagent workflows
- Monitor API usage to stay below rate limits
Suggested Fix
- Individual AbortController per subagent instead of shared instance
- Per-subagent error handling with isolated retry logic
- Distinguish user cancellation from API error responses
- Graceful rate limit backoff without terminating other agents
- Preserve backwards compatibility with pre-v1.0.85 behavior
Additional Context
- This affects all users running multi-subagent workflows
- Particularly impacts power users leveraging Claude Code's parallel processing capabilities
- The bug makes the Task tool's parallel execution unreliable for production workflows
- Error occurs consistently across different operating systems and terminal environments
- Issue becomes more frequent with higher API usage volumes
Before (v1.0.61): Individual Error Handling ✅
// Each subagent gets its own independent error handling
function query({
prompt,
options: {
abortController = createAbortController(), // Individual per subagent
allowedTools = [],
}
}) {
// Each child process is independently managed
const child = spawn(executable, [...args], {
signal: abortController.signal, // Individual process control
cwd,
stdio: ["pipe", "pipe", "pipe"],
env
});
// Individual cleanup handler - only affects THIS subagent
const cleanup = () => {
if (!child.killed) {
child.kill("SIGTERM"); // Only kills THIS subagent
}
};
// Individual abort listener - isolated to this subagent
abortController.signal.addEventListener("abort", cleanup);
// Individual error handling - doesn't affect other subagents
child.on("error", (error) => {
if (abortController.signal.aborted) {
query2.setError(new AbortError("This specific subagent was aborted"));
} else {
query2.setError(new Error(`This subagent failed: ${error.message}`));
}
});
// Individual cleanup on completion
processExitPromise.finally(() => {
cleanup(); // Only cleans up THIS subagent
abortController.signal.removeEventListener("abort", cleanup);
});
}
// Rate limit handling in v1.0.61
child.on('error', (error) => {
// Individual agent handles its own errors
// No cascade termination to other agents
handleIndividualFailure(agentId, error);
});
After (v1.0.89): Shared AbortController Cascade ❌
// Problematic shared pattern that breaks everything
const globalAbortController = new AbortController(); // SHARED across all subagents
// All subagents share the same controller
function spawnSubagent(agentId) {
const child = spawn(executable, [...args], {
signal: globalAbortController.signal, // SHARED signal - problem!
// ...
});
// This cleanup function kills ALL subagents
const cleanup = () => {
if (!child.killed) {
child.kill("SIGTERM"); // Kills ALL subagents when ANY fails
}
};
// ALL subagents listen to the SAME signal
globalAbortController.signal.addEventListener("abort", cleanup);
}
// Rate limit handling that triggers global abort
function handleRateLimit(status) {
if (status === 429) {
globalAbortController.abort(); // Kills ALL subagents!
}
}
// When ANY subagent hits an error, ALL die
child.on("error", (error) => {
globalAbortController.abort(); // CASCADE TERMINATION!
});
Key Differences:
v1.0.61 (Good):
- ✅ Individual AbortController per subagent
- ✅ Isolated error handling - one failure doesn't affect others
- ✅ Selective termination - can kill individual agents
- ✅ Fault tolerance - other agents continue working
- ✅ No cascade failures
v1.0.89 (Broken):
- ❌ Shared AbortController across all subagents
- ❌ Cascade error handling - one failure kills all
- ❌ All-or-nothing termination - can't kill individual agents
- ❌ No fault tolerance - single point of failure
- ❌ Cascade termination bug
What Changed:
// v1.0.61: Individual management
const agent1Controller = new AbortController(); // Agent 1's controller
const agent2Controller = new AbortController(); // Agent 2's controller
const agent3Controller = new AbortController(); // Agent 3's controller
// v1.0.89: Shared management (BROKEN)
const sharedController = new AbortController(); // ALL agents share this
// When sharedController.abort() is called, ALL agents die
The fix is simple: Revert to the v1.0.61 pattern where each subagent gets its own AbortController for isolated error handling, instead of the
shared controller that creates cascade failures.
This explains why "immediately launch ten subagents in parallel" worked perfectly in v1.0.61 but became unreliable in v1.0.89 - the underlying
architecture broke fault isolation.
Impact on Usability
This represents a major regression in Claude Code's usability and reliability:
- Breaks advertised functionality: Multi-subagent parallel processing was a key differentiator
- Destroys user confidence: Unpredictable termination makes users hesitant to use subagents for important work
- Productivity loss: Users lose hours of work when all subagents terminate unexpectedly
- Workflow disruption: Forces users to avoid or significantly limit one of Claude Code's most powerful features
- Trust erosion: Makes Claude Code feel unreliable for production workflows where consistency matters
The severity is compounded by the fact that this worked reliably in previous versions, making it a clear step backward in user experience. Users who upgraded expecting improvements instead lost access to functionality they previously relied upon.
Priority
High - This breaks a core advertised feature of Claude Code and significantly impacts productivity for users relying on multi-subagent workflows.
Additional Context
<img width="455" height="1189" alt="Image" src="https://github.com/user-attachments/assets/f22fc368-02bd-40ed-ae58-7017e0042a61" />
This issue has 5 comments on GitHub. Read the full discussion on GitHub ↗