[BUG] Background task-notification bodies silently truncated at a hardcoded 100,000 chars — TASK_MAX_OUTPUT_LENGTH does not apply and no saved-output path is included
Environment
- Claude Code v2.1.2xx (observed live on multiple 2.1.23x sessions; cap verified still present in the v2.1.257 binary)
- macOS
- Multi-agent setup: an orchestrator session dispatching custom subagents via the Agent tool; subagents run in the background and their final reports arrive as task notifications
What happens
When a background subagent finishes and its final message is delivered to the parent session as a task notification, the notification body is truncated to ~100,000 characters. The debug log records it, e.g.:
enqueuePendingNotification: task-notification capped from 163125 to 100040 chars
Observed on three real runs in one working session (returns of 163,125 / 120,095 / 109,005 chars each delivered as ~100,040). The parent receives a copy silently missing the tail — in an orchestrator workflow that audits or synthesizes from subagent reports, the parent can wrongly judge a complete report as malformed/incomplete, or miss content entirely, because nothing in the delivered body points at the full text.
Why this looks like a gap rather than the documented behavior
The documented knob for subagent output size is TASK_MAX_OUTPUT_LENGTH (env-vars reference: "Maximum number of characters in subagent output before truncation (default: 32000, maximum: 160000). When truncated, the full output is saved to disk and the path is included in the truncated response").
Two mismatches:
- The variable does not govern this path. In the sessions above,
TASK_MAX_OUTPUT_LENGTHwas set to64000, yet the notification clip landed at 100,040 — so the task-notification path uses its own limit. - No recovery pointer. Unlike the documented truncation behavior, the capped notification does not include a saved-to-disk path for the full output. The full text survives only if the subagent's own instructions happened to save it to a file.
Where the cap lives (bundle inspection, v2.1.257)
The enqueue site truncates with a compile-time constant, no env lookup:
if (Br.mode === "task-notification" && typeof Br.value === "string") {
let Ts = _d(Br.value, FQn);
if (Ts !== Br.value)
t(`enqueuePendingNotification: task-notification capped from ${Br.value.length} to ${Ts.length} chars`, {level:"warn"})
with the constant defined as a bare literal in a row of constants:
var aJ=50000,WNe=500000;var QSt=4,LQn=400000,MQn=200000,Fw=50,NQn=1e4,$7e=1e4,FQn=1e5;
FQn = 1e5 = 100,000; the observed 100,040 is the content plus the truncation marker. A sweep of the env-vars reference finds no variable that reaches this path.
Expected / requested
Any of these would resolve it, in order of preference:
- Honor
TASK_MAX_OUTPUT_LENGTH(or a dedicated documented variable) on the task-notification path, so the limit is configurable up to its documented maximum instead of hardcoded. - On truncation, save the full output to disk and include the path in the truncated notification — parity with the documented
TASK_MAX_OUTPUT_LENGTHbehavior, so the parent can always recover the full report. - At minimum, document the 100,000-char task-notification cap in the env-vars/tools-reference output-limits sections, so orchestrator authors know to design around it (e.g., instruct subagents to save reports to a file and parents to read the file for large returns — the workaround we ended up with).
Workaround for anyone hitting this
Have subagents write their full report to a file and include the path in their final message; instruct the parent to Read the saved file whenever a return approaches ~100KB, and never treat a large notification body as the complete text.