Subagent failures and diagnostics

DataMind Oda can hand part of a task to a subagent, and that run can fail, be refused, or be stopped before it finishes. This page is the catalogue of the messages that tell you so, and how to read them. How delegation works is in Delegating work to subagents; what a settled subagent sends is in Subagent settlement and results.

When a run does not complete

A run that does not complete brings back three parts: a headline that names the ending, a Diagnostic: line, and the text the subagent produced before it ended, under Partial output before the run ended:. The headline tells you the run's stop reason:

HeadlineStop reasonWhat it means
subagent run was cancelledabortedThe run was stopped, by you or by an ancestor.
subagent run failederrorThe run ended with a problem; the Diagnostic: line names it.
subagent run hit its token limit before finishingmax-tokensThe run reached its token limit before it could finish.
subagent declined the taskrefusalThe run refused the work, or its work was blocked.
subagent run ended abnormally (<reason>)another kindThe run ended for a kind outside the four above; the reason is named in brackets.

The diagnostic line

The Diagnostic: line is the run's own account of what went wrong, written to be safe to show: it never carries the subagent's raw output, file contents, paths, task text, environment values or credentials. What it names is where the run stopped (a stage) and what kind of problem it was (a category).

What a failure line reads like, backend by backend

The exact wording depends on the backend the subagent ran on. The ACP, Claude Code and Codex pages list their stages and categories in full: ACP, Claude Code, Codex.

BackendThe line startsStage valuesCategory values
ACPSubagent failure (provider: ACP; stage: <stage>; category: <category>)initialize, new-session, prompt, process, teardownprotocol, configuration, transport, process-start, process-exit, remote-limit, unknown
SDKSubagent failure (provider: SDK; stage: <stage>; category: <category>)initialize, session-run, shutdownconfiguration, protocol, transport, child-error, child-disposed, child-unknown, missing-terminal, unknown
Claude CodeProduct subagent failure (product: Claude Code; stage: <stage>; category: <category>)query-start, query-run, process, teardownlimit, product-error, invalid-result, process, unknown
CodexProduct subagent failure (product: Codex; stage: <stage>; category: <category>)initialize, thread-start, turn-start, turn, process, teardownlimit, access-policy, service, transport, product-error, invalid-result, unknown, process

When a request is refused

Each message below tells you a request was not allowed and names its own reason. The delivery rules themselves are in Continuable subagents.

Starting and resuming

Messages and interrupts

Stops and closing

Listing

When a request from the app fails

Prompts and interrupts can also be driven from the app itself. A failed request there carries a stable code; these are the codes and their messages.

CodeThe messageWhat it means
gateway/bad-requestinvalid payload for <method>The request was malformed and was not delivered.
gateway/cancelledsubagent prompt was cancelledThe request was cancelled before delivery; this is not a failure.
subagent/attachment-invalidno message of its ownAn image in the prompt was not accepted: too many images, an unreadable one, or a subagent whose model takes text only.
subagent/not-resumablesubagent cannot be resumedThe subagent's saved record cannot be read, so it cannot be brought back.
subagent/unauthorizedsubagent does not belong to this parentThe caller is not the subagent's parent.
subagent/delivery-unavailablesubagent follow-up is temporarily unavailableThe subagent cannot take a message right now, for example when the active limit is reached or it is winding down; try again later.
subagent/parent-unavailableparent session "<id>" is not liveThe chat that started the subagent is not live.
subagent/invalid-time-zoneclientTimeZone must be UTC or a valid IANA Area/Location nameThe time zone sent with the request was not recognised.
gateway/internalsubagent prompt failed or subagent interrupt failedThe request failed for another reason.

When closing a subagent goes wrong

A subagent that does not close cleanly does not read as a clean ending: Oda reports its run as an error instead of a completion, withholds its output, and records the problem as a teardown failure.

Closing continues past a failure: when a chat is archived, its running subagents are stopped one at a time, and one that fails to stop is noted while the others still stop. See Chat with Oda.

Questions, answered

Does a cancelled run count as a failure?

No. A cancelled run settles as aborted: the headline reads subagent run was cancelled and no diagnostic is attached. A run you stop from the chat reads the same way; a stopped one-shot background run reports through its job as killed instead, with the reason you gave.

What does subagent run ended abnormally (<reason>) mean?

The run ended for a kind outside the four standard stop reasons, and Oda names that kind in brackets. Treat it like a failure: read the Diagnostic: line and the partial text to see what the subagent managed to do before it stopped.

What do stage and category in a diagnostic mean?

The stage says where the run stopped, and the category says what kind of problem it was. For example, stage: prompt; category: remote-limit says the run stopped while the task was being worked on, because the far side reported one of its own limits.

Why does a diagnostic end with [diagnostic truncated]?

Because it was longer than its size cap, so it is cut short and marked. The stage, the category and the beginning of the account are still there; only the tail was dropped.

Can I retry work a failed run did not finish?

Yes, start a new delegation for the part that is left. A continuable subagent can also be brought back and sent what remains, and a run that stopped at its token limit keeps its partial text so you can see what is missing.

What does it mean that subagents are draining?

Some subagents are being closed right now. Closing a subagent closes any subagents it started first, and while a closing runs, a new operation of that kind is held back instead of being accepted part-way; the refusal reads continuable subagents are draining; the operation was not admitted. Ask again once the closing has finished.

What does subagent listing was cancelled mean?

Reading the list of a chat's subagents was cancelled before it finished. Nothing about the subagents themselves changed: it is a reading that stopped, not a subagent failing. Ask to list again.

Why was a subagent not established because its parent was closing?

The parent was already closing down when the start ran, so no subagent was started: the refusal reads subagent parent "<id>" is being disposed; the child was not established. Nothing half-started is left behind; start the work again if it is still needed.

Why was a follow-up refused while a subagent is winding down?

The subagent was already closing, and one that is closing cannot take a message. The refusal says whether the message was not delivered, or, once its intake had closed, not accepted; nothing was delivered by it.

What happens when a subagent does not close cleanly?

Its run is reported as an error instead of a completion, and its output is withheld rather than returned as a result; the problem is recorded as a teardown failure. When this happens while a chat is archived, the other subagents still stop.