[BUG] Subagent burns 256k output tokens on thinking across four max_tokens turns, produces nothing, and the stall watchdog never fires

Status Open
Reported on v2.1.280
Maintainer reply None cached
Activity 1 comment · opened Sep 27, 2026

Preflight Checklist

  • [x] I have searched existing issues and this hasn't been reported yet
  • [x] This is a single bug report
  • [x] I am using the latest version of Claude Code

What's Wrong?

A background subagent spent its entire output budget on reasoning across four separate turns, made four tool calls in 38 minutes, produced no file and no final text, and nothing surfaced to the parent session. No error, no warning, no notification. The stall watchdog never fired, because thinking tokens keep the stream alive.

Environment

  • Claude Code 2.1.280, WSL2 Ubuntu on Windows 10
  • Subagent model claude-sonnet-5, launched with the Agent tool in the background
  • Parent session on claude-opus-5
  • Task: write a single module of roughly 900 lines

Numbers, taken from the subagent's own transcript (~/.claude/projects/<project>/<sessionId>/subagents/agent-<id>.jsonl)

| | |
|---|---|
| Assistant turns | 39 |
| Turns with stop_reason: max_tokens | 4, each exactly 64000 output tokens |
| Output tokens total | 258299 |
| Thinking tokens | 256478, or 99.3% of all output |
| Tool calls after the first 29 seconds | 4, all inside one 14 second window |
| Elapsed from the end of the working phase to the last turn | 38 minutes |
| Files written | none |
| Final assistant text | none |

Timeline, abridged, timestamps as recorded

15:38:42  agent starts, 29 turns of Read and Bash in 29 seconds, ordinary work
15:39:11  last tool call of the working phase (Read)
15:48:09  stop_reason=max_tokens   output_tokens=64000   thinking=63998   no tool call
15:57:56  stop_reason=max_tokens   output_tokens=64000   thinking=63999   no tool call
15:58:17  four tool calls in 14 seconds, brief recovery
16:07:59  stop_reason=max_tokens   output_tokens=64000   thinking=63999   no tool call
16:17:32  stop_reason=max_tokens   output_tokens=64000   thinking=64000   no tool call
          transcript ends here, no file, no final text

The agent was composing the whole 900 line file inside its reasoning, hitting the 64k ceiling, and starting over. It did this four times.

Why nothing caught it

The async stall watchdog resets on every stream chunk and on a roughly 1 Hz progress tick, mechanism described in #85265. Thinking tokens are stream chunks, so a turn that emits 64000 thinking tokens and nothing else looks perfectly healthy to it. From the parent session there is no signal either: no tool call, no partial output, no notification that a turn ended on max_tokens. The parent cannot tell this apart from an agent doing careful work.

How this differs from the neighbouring reports

  • #83848, the transcript stops mid-conversation. Here it does not stop, it keeps producing complete max_tokens turns.
  • #79865 and #85265, silence after a tool_result, agent killed by the 600s watchdog. Here tokens flow the whole time and the watchdog never fires at all.
  • #82803 and #79415, degenerate or corrupted output consuming max_tokens. Here the output is well formed reasoning, it is simply never externalised.

What Should Happen?

  1. stop_reason: max_tokens on a subagent turn should surface to the parent session immediately. The information is already written to the transcript and currently reaches nobody.
  2. Repeated max_tokens turns with no tool call between them should count as a stall. Two in a row is already pathological, four is unambiguous.
  3. The stall watchdog should not treat a thinking-only turn as progress, or should hold a separate budget for it.

Error Messages/Logs

None, and that is the point of this report. The only trace anywhere is "stop_reason":"max_tokens" inside the subagent transcript.

Steps to Reproduce

  1. Launch a background subagent with the Agent tool and ask it for a single file of roughly 900 lines in one shot, with no instruction about how to write it.
  2. Watch the parent session. Nothing arrives, no error and no notification.
  3. Read ~/.claude/projects/<project>/<sessionId>/subagents/agent-<id>.jsonl and grep for "stop_reason":"max_tokens".

Honest caveat on reproducibility: I observed this once, with the transcript above as evidence. I did not then run a controlled repeat, because the relaunch used the workaround below and completed normally. So the cause is strongly supported by the transcript but the trigger condition, asking for the entire file in one response, is inferred rather than proven across repeats.

Workaround

At the prompt level, and it is reliable. Instruct the subagent to write the file incrementally: first section on disk within 10 minutes, then extend with Edit in chunks of at most 300 lines, and explicitly never compose the whole file in thinking before writing it. The identical task then finished in 12 minutes with the file written.

For detection from outside, two or more max_tokens turns with no tool call between them is a reliable signature. A small script that reads the transcript tail and reports time since the last tool call, tool_use ids with no matching tool_result, and the count of max_tokens turns is here together with a writeup: https://gist.github.com/Sundwell/540e515f4ed098ecb0c785e87e024c20

Related: #91093 asks for a liveness signal for background subagents. Surfacing max_tokens would be the cheapest possible version of that.

Claude Model

claude-sonnet-5 for the subagent, claude-opus-5 for the parent session

Is this a regression?

Not sure, first time running a task of this shape

View original on GitHub ↗

This issue has 1 comment on GitHub. Read the full discussion on GitHub ↗