Sume Format run failed: error codes, details, and what to do
A failed Sume Format run names its cause in error.code. Here is each code with its details fields, what gets billed, and whether to continue or retry.

When a Sume Format run fails, its receipt comes back with status: "failed", an error.code that names the cause, and usually an output_error whose details say more. The code decides the next step: fix the input or the schema, continue the run with previous_run_id to keep the clips it made, or retry with a new Idempotency-Key.
The codes and advice below come from Sume's Errors and spend and Structured output pages, read on 2026-09-26. For the error envelope and the 4xx codes a create call can return, see Sume API errors and rate limits.
What does a failed run's receipt contain?
A 202 never turns into a create error later: once you hold a receipt, failures arrive on it. A failed receipt carries:
status: "failed"andnext_action: "none", as on every terminal run.error: { code, message }. Branch oncode, and logmessagerather than matching on it.output_error: { code, message, details }in most cases. Most of the fields named in the table below sit in itsdetails.artifacts[]with everything the run generated, andoutputwith whatever partial result satisfied your schema.primary_output_url: null, always.if (run.primary_output_url)stays a safe test for “the deliverable exists”.
{
"data": {
"status": "failed",
"output": null,
"output_error": { "code": "unattended_blocked", "message": "no avatar matched the brief, so no video was made." },
"error": { "code": "unattended_blocked", "message": "no avatar matched the brief, so no video was made." }
}
}Which failure codes can a run report?
Treat this set as open: new codes may appear, so handle the ones you know and fall through on the rest instead of switching exhaustively.
| `error.code` | What happened | Fields to read | Next step |
|---|---|---|---|
unattended_blocked | The run hit a gate it could not pass without a person: no avatar matched the brief, or an input it would have asked about in chat was missing. message is written to be shown. | harvested, and assembled_deliverable: false | Fix the input or the brief; retry with a new key. |
output_schema_unsatisfied | The result did not match your output_schema, or referenced media the run did not produce. | rejected_urls[] (first 10 only) or violations[], plus harvested | Compare harvested with what your schema requires. Loosen the field to nullable, or change the instruction. |
deliverable_missing | The Format declares media in io.output_kind, and the run made none. | declared_output_kind, plus harvested | Retry. If it repeats, the input is not what the recipe expects. |
primary_output_missing | The result satisfied your schema, but the primary_output_key you named is empty. | primary_output_key; the partial is on output | Continue the run to fill the gap, or retry. |
agent_reported_failure | The run itself reported that it did not deliver: an explicit fail, failed or stand-in media slots, or a primary of the wrong media type. | reason (explicit_failed, slots_failed, primary_not_deliverable), plus non_delivered_slots[] or primary_media_type | Continue the run, or re-fire with a new key. Its clips are real. |
incomplete_assembly | The run reached its time limit with generation jobs still unfinished. | pending_job_count, pending_jobs[] | Continue the run with previous_run_id. |
output_extraction_failed | With reason: harvest_threw, the host's own harvest crashed after the run finished. | reason, thrown | A host defect: report the run id. |
mcp_unavailable | The Sume MCP tools the run needed did not attach, so it failed before the model ran. | retryable: true, charged: false | Retry with a new key. |
provider_unavailable | The model's provider stream was cut, and its reconnects ran out before the deliverable. | retryable: true | Retry with a new key. |
format_run_failed | The generic failure. A run that wanted to spend past its cap lands here. | message, and usage | Compare usage.billable_amount_usd_micros with usage.generation_spend_cap_usd_micros. |
Does a schema mismatch fail the run?
Yes, over the API. Runs over the API are unattended, so a projection failure is a run failure: status is failed, and error carries the same reason as output_error. In the Agents UI, where a person reads the thread, the same shape stays completed as a draft.
One case stays completed: output_extraction_failed with reason: harvest_unavailable, where the media could not be read while the run finalized. The receipt fills in on your next read; if it does not, retry with a new key. To keep scenes readable on a failed run, see Partial results from a failed AI video run.
Should I retry or continue a failed run?
The per-code advice above follows three rules from the docs:
- Retry with a new
Idempotency-Key. The old key is bound to the receipt you already have, and reusing it returns that same failed receipt. - Continue instead when the failure left clips behind, as with
incomplete_assembly: the finished clips are on the thread and are not regenerated. Regenerate one scene of an AI video shows the call. - Fix the cause first when it is yours: the brief for
unattended_blocked, and usually a schema that demands a file the Format never makes foroutput_schema_unsatisfied.
Am I billed for a failed run?
Generation that finished before a failure is billed, and a later step failing does not refund it. mcp_unavailable fails before any generation runs: details.charged is false, and nothing was billed.
Read spend off the receipt. usage.billable_amount_usd_micros is the generation spend counted against the cap, and usage.debited_usd_micros is what the wallet actually deducted, the agent's own LLM turn included. A run that wanted to spend past its cap ends failed with format_run_failed, and usage shows how close to the cap it got.
How does a failed run arrive over a webhook?
The same run arrives with status: "ERROR", outcome: "error", and error.code mirroring payload.error.code. payload is byte-identical to data from GET /v1/format-runs/{run_id}, so one handler can branch on the same code for webhooks and polls; it is null only when the receipt is over 1 MiB, and then error.result_url says where to fetch it. A canceled or skipped run never delivers a webhook.
Sources
Related posts
Written by Sume