Format run agent_reported_failure vs deliverable_missing: retry or not
agent_reported_failure means the run said it did not deliver; deliverable_missing means it made no media at all. Both leave a failed run, but the retry differs.

agent_reported_failure means the run's own accepted receipt said it did not deliver, while deliverable_missing means the Format is declared to produce media (io.output_kind) and the run made none. Both end in status: "failed" with primary_output_url: null. The difference decides your next call: for the first the clips on output are real and a retry does not regenerate them; for the second, if it repeats, the input is not what the recipe expects.
The meanings below come from Errors and spend and Structured output.
What does each code mean?
The failure codes sit in error.code on the receipt, and the structured-output ones are mirrored in output_error.code. Treat the set as open; the docs say new codes may appear.
| Code | What happened | Where the evidence is |
|---|---|---|
| agent_reported_failure | The run's accepted receipt says it did not deliver: an explicit-fail payload, failed or stand-in media slots, or a primary of the wrong media type | details.reason: explicit_failed, slots_failed or primary_not_deliverable; output carries the ledger |
| deliverable_missing | The Format declares media output and the run made none | details.declared_output_kind and a harvested count by media type |
| primary_output_missing | Your schema matched but the primary_output_key you named is empty | details.primary_output_key; output carries the partial |
| incomplete_assembly | Time limit reached with generation jobs unfinished | details.pending_job_count and pending_jobs[] |
How do I tell them apart in code?
Branch on error.code, and read details before you retry. agent_reported_failure with slots_failed carries non_delivered_slots[], which tells you which scenes did not come out. A primary that is audio or a still under a video key shows primary_media_type, the signal that the run delivered something, just not the thing the Format promises.
def next_step(run: dict) -> str:
err = run.get("error") or {}
code = err.get("code")
d = err.get("details") or {}
if code == "incomplete_assembly":
return "continue with previous_run_id"
if code == "agent_reported_failure":
if d.get("reason") == "slots_failed":
return "continue the run, then re-read non_delivered_slots"
return "read output ledger, then continue or re-fire"
if code == "deliverable_missing":
return "check the input against the recipe, retry once"
if code == "primary_output_missing":
return "continue the run to fill the gap"
return "fall through: log code and request_id"Should I retry, continue or change the input?
The docs give three moves. Retry a failed run with a new Idempotency-Key, because the old key is bound to the receipt you already hold. When the failure left clips behind, prefer continuing the run with previous_run_id over a fresh one, so the finished work is not regenerated. And when deliverable_missing repeats, change the input or brief; another identical retry will not help.
Continuing needs the previous run to be terminal and on the same Format, or the create is rejected with previous_run_not_terminal (409) or previous_run_format_mismatch (400).
What does a failed run cost?
Generation that finished before the failure is billed, and a later step failing does not refund it. Compare usage.billable_amount_usd_micros with usage.generation_spend_cap_usd_micros to see how close the run came to its cap. Score runs on primary_output_url, which is null on every failure, and do not assume a non-empty artifacts[] means a finished deliverable: the docs say the harvested media on agent_reported_failure are the run's ledger of what was made, not an assembled cut.
See also the full list of Format run failure codes and continuing a run after incomplete assembly.
Sources
Related posts
More in Formats
- Format run failed provider_unavailable or mcp_unavailable: retry rules
provider_unavailable and mcp_unavailable are Sume-side Format run failures: retry with a new Idempotency-Key. provider_credits_exhausted waits.
- Format run instruction: 8000 characters accepted, about 4000 carried
A Sume Format run instruction accepts 8,000 characters, but only the first ~4,000 reach the agent as prompt text. Put long data in input, carried whole.
- Format run provider_credits_exhausted: not your balance, wait
provider_credits_exhausted means Sume's model provider account ran out of credit, not your balance. Do not retry right away; wait, then use a new key.
- Format run status_url or result_url: which one do I poll?
Poll status_url for a small payload, then read result_url once the run is terminal. result_url answers 409 run_not_completed while the run is in flight.
Written by Sume