Failed Format run codes: retry, continue, fix input or wait

Eleven error.code values a failed Sume Format run can carry, grouped by response: continue with previous_run_id, retry with a new key, fix input, or wait.

6 min readSume
All posts

A failed Sume Format run falls into four buckets, and the error.code tells you which. Some failures should continue the same run with previous_run_id, because the finished clips are on the thread and a fresh run would not regenerate them. Some should retry with a new Idempotency-Key. Some need a change to your input or schema. One, provider_credits_exhausted, should not be retried right away at all. Treating all eleven the same way either wastes spend or gives up on work that was nearly done.

The four buckets

The Formats error page lists the codes on a failed run. Read them with two facts in mind. First, the receipt still lists every artifact the run generated, and output carries whatever partial result satisfied your schema, so a failed run is often a partial delivery rather than nothing. primary_output_url is null on every failure, which makes if (run.primary_output_url) a safe test for whether the deliverable exists. Second, the old key is bound to the receipt you already have, so any retry needs a new key.

read 2026-10-03
error.codeWhat happenedResponse
incomplete_assemblyTime limit hit with generations unfinishedContinue with previous_run_id
primary_output_missingSchema met, primary key emptyContinue, or retry
agent_reported_failureRun said it did not deliverRead details.reason, continue or re-fire
unattended_blockedNeeded a person: no avatar match or missing inputFix input or brief, new key
output_schema_unsatisfiedResult did not fit your schemaLoosen to nullable or change the instruction
deliverable_missingMedia Format produced noneRetry once, new key
mcp_unavailableTools did not attach; nothing chargedRetry, new key
provider_unavailableProvider stream cut; retryableRetry, new key
output_extraction_failedProjection could not runRead again, then retry
provider_credits_exhaustedSume's provider account, not your balanceWait, do not retry now
format_run_failedGeneric, including spend capCompare billable with the cap

A router you can run

The map below turns the code into one of a handful of actions and caps the number of automatic retries, so a flapping provider ends in a page instead of an infinite loop. Unknown codes fall through to a human, because the docs say to treat the set as open. It runs as-is.

ROUTES = {
    "unattended_blocked": "fix_input",
    "output_schema_unsatisfied": "fix_schema_or_instruction",
    "deliverable_missing": "retry_new_key_once",
    "primary_output_missing": "continue",
    "agent_reported_failure": "continue",
    "incomplete_assembly": "continue",
    "output_extraction_failed": "read_again_then_retry_new_key",
    "mcp_unavailable": "retry_new_key",
    "provider_unavailable": "retry_new_key",
    "provider_credits_exhausted": "wait_do_not_retry_now",
    "format_run_failed": "check_spend_cap",
}

def route(error_code: str, attempts: int, max_attempts: int = 2) -> str:
    action = ROUTES.get(error_code, "page_a_human")  # the set is open
    if action.startswith("retry") and attempts >= max_attempts:
        return "page_a_human"
    return action

for code, n in [("incomplete_assembly", 1), ("provider_unavailable", 1),
                ("provider_unavailable", 2), ("brand_new_code", 0)]:
    print(code, n, "->", route(code, n))

Money and partial work

Failure does not erase what was generated. Generation that finished before a failure or a cancel is still billed, which is another reason to prefer continuing a run over starting one: the finished clips are reused. For the cost of a failed attempt, read /v1/usage?run_id= and use the summary rather than summing rows. A mcp_unavailable failure is the exception worth knowing: its details say nothing was charged because no generation ran.

Over a webhook

The same classification arrives on the webhook. A failed run is delivered as status: ERROR with outcome: error and error.code mirroring the receipt, and a run that completed but could not fill your schema arrives as status: OK with outcome: degraded. Route both through the same table, and run the router in the worker that handles the stored event rather than inside the HTTP handler.

Alerting on codes

Count failures by code per day. A spike in provider_unavailable or mcp_unavailable points at Sume or its dependencies, and the right response is patience and backoff. A spike in output_schema_unsatisfied or unattended_blocked points at your Formats or inputs, and the right response is an edit. A single provider_credits_exhausted is Sume's provider account running out of credit, which is not yours to fix. Different owners, different channels: wire each group to the right one instead of one noisy alert.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume