Error Propagation
Failures in subagents decide whether a system recovers or fails silently. Learn structured error context, the two deadly anti-patterns, and access-failure vs empty-result.
In multi-agent Claude systems, how a subagent reports failure determines whether the coordinator recovers gracefully or fails silently. The difference between a resilient pipeline and a fragile one is almost never the model — it is the shape of the error that flows back upstream.
Structured error context: four required elements
- Failure type — categorise it:
transient(timeout, rate limit; retry may work),validation(bad input; fix the query),business(rule violation; escalate), orpermission(access denied; needs authorization changes). - Attempted action — the exact query, parameters, and target.
Searched academic DB for 'renewable energy policy', 2022-2024beats a baresearch failed. - Partial results — preserve whatever was retrieved before failure. If three of five sources returned before a timeout, keep them.
- Alternative approaches — suggest domain-specific recovery: retry with narrower params, try another database, use cached results.
{
"status": "partial_failure",
"failureType": "transient",
"attemptedAction": {
"tool": "academic_search",
"query": "renewable energy policy",
"dateRange": "2022-2024"
},
"partialResults": [
{ "source": "journalA", "retrieved": true },
{ "source": "journalB", "retrieved": true }
],
"alternativeApproaches": [
"retry with narrower date range",
"fall back to cached results"
]
}The two anti-patterns
Silent suppression is the deadliest: a subagent catches an error and returns { "results": [], "status": "success" }. The coordinator believes the search ran and found nothing, so it never retries and never seeks an alternative. The output looks complete but hides an undetectable gap. Workflow termination is the opposite failure: one subagent's error kills the whole pipeline, throwing away the successful work of every other subagent.
Swallow the error and return an empty result marked successful. The coordinator sees a clean run with no matches, so it never retries or seeks an alternative.
except TimeoutError:
return {"results": [], "status": "success"} # silent suppressionPropagate a structured error with failure type, attempted action, and any partial results so the coordinator can recover intelligently.
except TimeoutError:
return {"status": "error", "failureType": "transient",
"partialResults": got_so_far}Catching a timeout and returning an empty-but-successful result is the single most dangerous error-handling bug. The coordinator cannot recover from a failure it cannot see. Always report the real status.
Access failure vs valid empty result
This is a heavily tested distinction. An access failure means the query never executed — timeout, connection error, permission denial — so a retry may be warranted. A valid empty result means the query ran successfully and genuinely found zero matches; that empty set IS the correct answer and no retry is needed. Confusing them causes either missing retries or wasted ones.
| Outcome | status | shouldRetry |
|---|---|---|
| Access failure (timeout) | error | true |
| Valid empty result (0 matches) | success | false |
Treat both a timeout and a genuine zero-match the same way — either retrying valid empty results forever, or giving up on recoverable access failures.
if not results: give_up() # conflates the two casesDistinguish them: an access failure never ran the query (retry), a valid empty result ran and found nothing (accept it — that is the answer).
if status == "error": retry() # query never executed
elif not results: accept() # 0 matches is the answerLocal recovery and coverage annotations
Subagents should attempt their own recovery first — retry with exponential backoff, try a fallback source — and only propagate errors they cannot resolve locally, always including the attempted action and any partial results. At synthesis time, add coverage annotations so gaps are visible: Section on geothermal energy is limited due to unavailable journal access. This stops a data gap from silently reading as 'this topic is irrelevant'.
Structured error context (type, attempted action, partial results, alternatives) lets a coordinator recover intelligently. The two anti-patterns are silent suppression and pipeline termination. Retry access failures; never retry valid empty results.
How the exam will try to trick you
The distractors below look right under time pressure — learn the tell.
- The trap
Catch the timeout and return
{ "results": [], "status": "success" }to keep the pipeline clean.Correct answerPropagate a structured error with failure type, attempted action, and partial results.
Why: The coordinator believes the search ran and found nothing, so it never retries — the gap is invisible.
- The trap
If one subagent times out, terminate the whole pipeline and report failure.
Correct answerIsolate the failure, keep every other subagent's results, and recover around it.
Why: Workflow termination throws away completed work — a disproportionate response.
- The trap
After retries fail, return a generic
search unavailablestatus.Correct answerReturn the failure type, the exact attempted query, partial results, and alternative approaches.
Why: A generic message hides the context the coordinator needs to recover intelligently.
- The trap
Retry a query that returned zero matches, since an empty result looks like a failure.
Correct answerAccept a valid empty result — the query ran and zero matches IS the answer.
Why: Retrying an unchanging outcome wastes resources; only access failures (query never ran) warrant a retry.
Key takeaways
- Report every failure with four elements: failure type, attempted action, partial results, and alternative approaches.
- Silent suppression (empty results marked 'success') hides gaps the coordinator can never recover from.
- Workflow termination discards good work from other subagents — isolate failures instead of killing the pipeline.
- Access failures (query never ran) may warrant retry; valid empty results (query ran, found nothing) must not be retried.
- Subagents should retry locally with backoff and only propagate what they cannot resolve.
- Add coverage annotations at synthesis so data gaps stay visible instead of masquerading as irrelevant topics.
Frequently asked questions
What is the difference between an access failure and a valid empty result?+
An access failure means the query never executed — a timeout, connection error, or permission denial — so the missing data might be recoverable with a retry. A valid empty result means the query ran successfully and legitimately found zero matches; that empty set is the correct answer and should not be retried. Structured error reporting must distinguish the two so the coordinator retries the right cases and wastes no effort on the wrong ones.
Why is silent error suppression dangerous in multi-agent systems?+
When a subagent catches an error and returns an empty result flagged as successful, the coordinator believes the operation completed and simply found nothing. It therefore never retries, never tries an alternative source, and never flags the gap. The final output looks complete but contains undetectable holes — the worst possible failure because it is invisible.