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.

5 min readSume
All posts

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.

Four close-looking Format run failures (read 2026-10-02)
CodeWhat happenedWhere the evidence is
agent_reported_failureThe 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 typedetails.reason: explicit_failed, slots_failed or primary_not_deliverable; output carries the ledger
deliverable_missingThe Format declares media output and the run made nonedetails.declared_output_kind and a harvested count by media type
primary_output_missingYour schema matched but the primary_output_key you named is emptydetails.primary_output_key; output carries the partial
incomplete_assemblyTime limit reached with generation jobs unfinisheddetails.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

All Formats posts

Written by Sume