Format run incomplete_assembly: continue it, do not pay twice

incomplete_assembly means the run hit its time limit with generation jobs unfinished. Read pending_job_count, then continue with previous_run_id.

4 min readSume
All posts

The short answer

A Format run that fails with incomplete_assembly reached its time limit before all of its generation jobs finished. The media you got back is not all the media the run paid for. Do not start a fresh run. Continue the failed run with previous_run_id: the finished clips are already on the thread, and the continuation does not generate them again.

That is the whole recovery path in Sume's documentation as of 2026-10-08. The rest of this page is how to read the failure, and what to send on the continuation so it stays cheap.

What the receipt tells you

A failed run still carries its artifacts. For incomplete_assembly the error details name the unfinished work, so you can decide whether continuing is worth it before you spend anything.

Fields on a failed incomplete_assembly receipt, as of 2026-10-08
FieldWhat it holdsWhat to do with it
error.codeincomplete_assemblyBranch on this code, not on the message text.
error.details.pending_job_countHow many generation jobs had not finishedLog it. A count of 1 is a different story from 12.
error.details.pending_jobs[]The unfinished jobs by nameUse them to tell the continuation which part is missing.
artifacts[]Every durable file the run did makeKeep these URLs. They are real, and they stay.
outputThe partial ledger, when your schema permits itRead output_error before you trust it.
primary_output_urlnull on any failureTest this field to know if the deliverable exists.

Continue, with a new key

A continuation is a new run with its own id, its own receipt, its own spend cap and its own single webhook. The original receipt never changes. Both runs share thread_id.

Send a new Idempotency-Key. The old key is bound to the receipt you already have, and the docs say to retry a failed run with a new key. Bind the same output_schema again, because the schema is per run and is not inherited.

Name the previous run, not the thread. A thread id in the body returns 400 unknown_parameter.

curl -sS -X POST "https://api.sume.com/v1/formats/acme/live-commerce/runs" \
  -H "Authorization: Bearer $SUME_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order-8823-lc-v1-finish-1" \
  -d '{
    "previous_run_id": "arun_e43e6c5cb2b74052",
    "instruction": "Finish only the clips that did not complete. Keep every finished clip.",
    "output_schema": { "name": "acme/live-commerce/v1", "schema": { "type": "object", "additionalProperties": false, "required": ["full_video"], "properties": { "full_video": { "$ref": "SumeMediaFile#" } } } },
    "primary_output_key": "full_video",
    "generation_spend_cap_usd": 8
  }'

When you cannot continue

The run you name must be continuable: its thread_id is not null, and it either completed or has a non-empty artifacts[]. A failed run that left work qualifies. Four refusals exist: 404 previous_run_not_found, 400 previous_run_format_mismatch, 409 previous_run_not_terminal, and 400 previous_run_not_resumable.

If you are inside a bulk queue, the item shows only the generic format_run_failed. Read the child receipt at GET /v1/format-runs/{run_id} to see the real code before you retry anything.

  • Spend on the original run is not refunded for generation that already finished.
  • The continuation has its own cap. The docs describe a single-scene retry as needing a fraction of a full-run cap, so size it to the missing work.
  • Webhook consumers get a second format.run.terminal event with the new run id, not a repeat of the first.

Deciding before you spend

The time limit is a platform bound, not something you set. A non-terminal receipt carries expires_at: the deadline after which Sume force-finalizes the run as failed. It is 90 minutes from created_at, or earlier when the run is older than 25 minutes and has been silent for 10. Long-form video is often 15 to 30 minutes of work, so a run that reaches this limit usually means a stuck or very large job, not a slow one.

Read GET /v1/format-runs/{run_id}/events on the failed run. It is a phase timeline (preparing, running, finalizing), not a log. If the at clock on the last entry stopped moving for several minutes, the run stalled. A continuation then has a good chance of finishing what the first run could not, because it starts a new turn on the same thread.

If pending_job_count is large compared with the number of artifacts, ask whether the brief asked for too much in one turn. Splitting a long brief into two runs, each with its own cap, keeps one stall from holding every clip.

  • Continue when artifacts exist and the missing part is a minority of the work.
  • Start a new run when artifacts[] is empty and previous_run_not_resumable would be the answer anyway.
  • Never reuse the failed run's Idempotency-Key; derive a new one from your item id plus a retry counter.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume