previous_run_id errors on a Format run: 404, 400 and 409 decoded

Continuing a Sume Format run can fail with previous_run_not_found, format_mismatch, not_terminal or not_resumable. Which are retryable and how to fix each.

5 min readSume
All posts

Sending previous_run_id on a Sume Format run can be refused four ways: 404 previous_run_not_found, 400 previous_run_format_mismatch, 409 previous_run_not_terminal and 400 previous_run_not_resumable. Only the 409 is worth retrying as is, after the earlier run finishes; the others need a different call.

Continuing is how an integration retries one scene without paying for the whole show again, so these refusals tend to appear in a retry path that was only tested on the happy case. This post gives each code, its cause and the fix.

What does each refusal mean?

The runs page lists the four refusals. They are all caught at create, so nothing runs and nothing is charged. A continuation is a new run with its own id, receipt, spend cap and single webhook, and the original run never changes.

Read code, not the status alone: two of the four share 400, and one shares 404 with the generic missing-run case.

previous_run_id refusals, read 2026-10-02
Status and codeCauseFix
404 previous_run_not_foundUnknown id, or another owner's runCheck the id and the key you hold
400 previous_run_format_mismatchThe run was created on a different FormatContinue it on the Format where it started
409 previous_run_not_terminalThe run has not finishedPoll it to terminal, then call again
400 previous_run_not_resumableNo thread_id, or neither completed nor any artifactsStart a fresh run

How do I know a run is continuable before I call?

Read it off its own receipt. The run must have a non-null thread_id, and it must either be completed or have a non-empty artifacts[]. A failed run that left work behind can be continued, and one that left nothing cannot, which is the previous_run_not_resumable case with details reporting previous_run_status, has_thread and artifact_count.

Checking first saves a write. The sample applies the documented test to a receipt you already hold.

def can_continue(run):
    if run.get("thread_id") is None:
        return False, "no thread_id"
    if run["status"] in ("queued", "processing"):
        return False, "not terminal: poll first"
    if run["status"] == "completed" or run.get("artifacts"):
        return True, "continuable"
    return False, "nothing to continue: start a fresh run"

print(can_continue({"thread_id": "thr_1", "status": "failed", "artifacts": [{"type": "video"}]}))
print(can_continue({"thread_id": "thr_1", "status": "failed", "artifacts": []}))
print(can_continue({"thread_id": None, "status": "completed", "artifacts": []}))

What else must a continuation get right?

Bind the same output_schema every turn, because it is per run, not inherited. Give the continuation its own Idempotency-Key, since the original key is bound to the original receipt; the retry-one-scene example uses a suffix such as -retry-sc7. Set a spend cap sized for the part you are redoing, not the whole show.

Continue by naming previous_run_id, never by sending a thread id: that is 400 unknown_parameter. See the unknown parameter post for how to read that suggestion.

Which Format does the run belong to?

The format mismatch is the one that surprises people running several Formats from one pipeline: the id is valid and yours, but you sent it to a different {handle}/{slug}. The receipt's format.id and format.slug name where it started, so store them next to the run id when you create it. For the whole retry flow end to end, read retry one scene on the same thread.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume