CLAUDE LABJP
FORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as OctoberFORK — Claude Code 2.1.212 changes what /fork does: it copies your conversation into a new background session with its own row in claude agents, so you can keep working. The old in-session subagent is now /subtaskLIMITS — WebSearch calls are now capped at 200 per session by default, and subagent spawns get the same 200 ceiling, so a runaway search or delegation loop stops on its ownMCPBG — MCP tool calls running past two minutes now move to the background automatically, keeping the session usable. Tune the threshold with CLAUDE_CODE_MCP_AUTO_BACKGROUND_MSPLANFIX — Fixed plan mode auto-running file-modifying Bash commands such as touch and rm without a permission prompt or an SDK canUseTool callbackSONNET5 — Claude Sonnet 5 is running on introductory pricing of $2 per million input tokens and $10 per million output. After August 31 it moves to $3 and $15IPO — Bankers are reportedly lining up investor meetings for Anthropic ahead of a possible public listing as soon as October
Articles/Claude Code
Claude Code/2026-04-24Intermediate

Diagnosing Claude Code Subagents That Stall or Never Return

Diagnostic flow for Claude Code subagents that freeze, return silently, or produce the wrong output shape — classified by symptom with runnable examples.

claude-code129subagent4troubleshooting87debug4

Anyone who has run Claude Code subagents seriously has hit the same wall: the agent is "running" according to the UI, but nothing is coming back. No logs, no errors, no progress — just a cursor blinking while you wonder whether to hit Ctrl+C. I have reflexively killed dozens of them before realising that the first thing to do is not to kill, but to classify.

Subagents are convenient, but they turn into black boxes the moment something unexpected happens inside them. Below is the diagnostic flow I settled on after getting stuck more times than I want to admit, grouped by the symptom you're actually seeing.

Classify the symptom — three questions first

Staring at logs without a hypothesis burns time. Start by answering these three questions explicitly — the answers narrow the root cause far more than any single log line will.

  • Did the subagent terminate quickly, or is it still running?
  • Is there any output at all, or is the channel completely silent?
  • Did the parent agent receive an error, or did the call end silently?

Cross these three axes and the root cause narrows fast:

  • Terminated × no output × error raised → prompt issue or missing tool permission
  • Long-running × no output × no error → tool-call loop or context saturation
  • Terminated × output present × no error → prompt interpretation drifted
  • Long-running × output present × no error → streaming not being drained on the parent side

The classifier is not a theoretical exercise. Each combination points at a completely different fix, so the time you spend on a one-minute mental sort pays back multiples of itself in debugging time.

Preserve state before you debug

Before you poke anything, capture the current session state. Recovering first and then saying "it doesn't reproduce" is how root causes get lost. This is the single discipline that has saved me the most hours.

# Tail the session log while the run continues
tail -f ~/.claude/logs/session-$(date +%Y%m%d)*.log > /tmp/cc-debug.log &
 
# Identify any running subagent processes
ps aux | grep -E "claude-(agent|code)" | grep -v grep
 
# Export the current parent conversation for later inspection
claude --export-conversation /tmp/cc-conv.json
 
# Capture a snapshot of open file descriptors — sometimes reveals a stuck Bash tool
ls -l /proc/$(pgrep -f "claude-agent" | head -1)/fd 2>/dev/null | head -30

Only after this snapshot should you run /subagent stop <name>. Stop it earlier and you lose the context that would have told you why it was stuck. I keep these four commands in a shell alias called cc-snap so they always run together.

Pattern 1: "running but silent" — the tool-call loop

This is by far the most common case. The subagent keeps calling the same tool in a cycle, so from the outside it looks active but never makes progress.

If your log shows consecutive calls like this, you're in a loop:

[subagent:tester] -> Bash: "npm test"  (turn 7)
[subagent:tester] -> Bash: "npm test"  (turn 8)
[subagent:tester] -> Bash: "npm test"  (turn 9)

The usual cause is a subagent that has no failure-analysis step. The test fails, and instead of diagnosing, the agent immediately re-runs it on the assumption that "maybe it was flaky." Then the same failure happens again. Then the cycle repeats until token budget or max_turns cuts it off.

The fix is to spell out the analysis step in the prompt and cap max_turns:

---
# .claude/agents/tester.md
name: tester
tools: Bash, Read
max_turns: 15
---
 
You are a test execution subagent. Follow these rules strictly.
 
1. Run the test suite exactly once.
2. On failure, list the failing test name plus three hypotheses for the cause.
3. Pick one verifiable hypothesis and confirm it by reading the relevant code.
4. If a fix is needed, describe it under a "Proposed Fix" section.
5. Before re-running the same test, write down why it failed last time.

With max_turns set, any runaway loop terminates at turn 15. When you see max_turns reached in the log, that is direct evidence the agent was looping — it saves you an hour of guessing. In practice I use 15 for test-running subagents, 8 for linting subagents, and 25 for refactoring agents that genuinely need more turns.

Pattern 2: "it finished fine" — errors that never surface

Sometimes a subagent swallows an error internally and reports success to the parent. A file write fails, but the final output is a cheerful "Done." — a silent failure that can go unnoticed until the next day, or the next deploy, or the next customer bug report.

The fix is to require a structured exit report from every subagent. The parent prompt should enforce it:

{
  "status": "success | partial | failed",
  "files_modified": ["src/utils/retry.ts"],
  "tests_passed": true,
  "unresolved_issues": [],
  "next_action_recommended": "..."
}

State explicitly in the subagent prompt: "the final output must be exactly this JSON shape, and missing any field counts as failure." That single sentence does more work than any amount of "please be careful" nudging. If work was incomplete, the agent must report "partial" or "failed" and enumerate what went wrong under unresolved_issues.

On the parent side you can then decide deterministically whether to accept, retry, or escalate. No more guessing whether "Done" means "all green" or "I ran out of ideas and gave up."

I have come to prefer this pattern even for small agents because the reviewable trail it leaves is worth more than the 30 seconds of prompt engineering it costs. When a bug appears weeks later, the exit report JSON is the first thing I look at.

Pattern 3: "returns, but the content is off" — no output schema

When the subagent responds but not in the shape you expected, the root cause is almost always that the prompt never defined what "the shape" is. Free-form text is ambiguous by default, and subagents will happily produce plausible-looking output that does not fit your parser.

Two things to do:

  1. Show at least one full example of the expected output. One concrete sample eliminates more ambiguity than a paragraph of description. LLMs imitate patterns far better than they follow abstract rules.
  2. Validate on the parent side and retry exactly once with a targeted hint if the schema is violated.
// Parent-side pseudocode
const result = await runSubagent('refactor-agent', task);
const parsed = tryParseJSON(result);
 
if (!parsed || !parsed.status) {
  // Schema violation — retry once with a specific reason
  return await runSubagent('refactor-agent', {
    ...task,
    retry_reason: 'Missing `status` field. Return exactly the JSON shape shown earlier.',
  });
}
 
// Only one retry. Beyond that, the design itself is the problem.
return parsed;

Unbounded retries just trade a silent failure for an infinite loop. Cap it at one. If the retry also fails, log the offending output and fall back to a human review path rather than another retry — because a pattern that fails twice in a row is rarely fixed by a third attempt.

Pattern 4: "returns eventually, but far too slowly"

A related but less-discussed symptom: the subagent does return, but only after five or ten minutes of silence. Usually the parent appears hung because it stops rendering streamed tokens while the subagent runs.

Two quick checks help here. First, verify the parent is actually draining the subagent's streaming output — if you invoked it from a script without attaching stdout, the buffering itself may be the issue. Second, look at whether the subagent is using a Bash call with a long-running command (a test suite, a webpack build) without an explicit timeout. Adding a sensible timeout (say, timeout 120s npm test) turns "hangs forever" into a crisp failure with a reason.

Still stuck? Reload agent definitions

If you changed .claude/agents/*.md but the behaviour hasn't changed, the definition is probably cached.

# Clear the cached agent definitions — harmless to run during development
rm -rf ~/.claude/cache/agents/
 
# Start a fresh session if the current one is wedged
claude --new-session

I was caught by this one embarrassingly many times. Updating the file, rerunning, and seeing the old behaviour convinced me I had a subtler bug — when really the file had never been re-read.

For the step beyond single-agent debugging, Claude Code subagent orchestration covers role separation across multiple agents. If your issue sits upstream — a long session losing coherence — read it alongside preserving context in long sessions. When tool chains themselves are what's breaking, production debugging for Claude Code Hooks pairs well with the patterns above.

When I had subagents running the Dolice Labs auto-posting as an indie developer, nothing drained me more than this exact silence. An error you can chase; a quiet hang gives you nothing to grab onto. Adding max_turns and a structured exit report didn't make every bug disappear, but it did guarantee that 'where it stopped' is always on record.

What to try next

If you have a subagent that is currently hanging, add max_turns to its definition file today. That single change makes most loop-based "never returns" problems visible instead of mysterious. It is the lowest-effort, highest-leverage fix in this article.

Once that is in place, move on to enforcing a JSON-shaped exit report. The moment output format is fixed, the "I have no idea what's happening" feeling stops reappearing — which, honestly, is half the battle.

Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Claude Code2026-05-02
Claude Code Stops Mid-Execution: Complete Diagnostic Guide
Diagnose why Claude Code freezes or stops mid-task. Covers context budget exhaustion, unresponsive subagents, infinite loops, and tool timeouts with actionable fixes for each scenario.
Claude Code2026-05-05
Claude Code MCP Connection Troubleshooting: A Complete Diagnostic Guide
A systematic approach to diagnosing MCP server failures in Claude Code—from config file validation to transport-layer debugging, crash recovery, and multi-server production patterns.
Claude Code2026-05-05
5 Common Claude Code Errors and How to Fix Them
A practical guide to the five most common Claude Code errors—Permission denied, rate limits, MCP connection failures, context overflow, and bash failures—with real causes and fixes for each.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →