provider_submission_failed 502: Sume could not start the job, retry

provider_submission_failed is a 502 meaning the job never started. By default it is retryable with retry_after_seconds 30 and next_action retry_later.

4 min readSume
All posts

provider_submission_failed is a 502 with the default message "Generation could not start." Its OpenAPI description is "Sume could not start the generation job. No result is available yet." In the actionability mapping, a 5xx with this code is retryable: true, with retry_after_seconds of 30 unless the server supplies another value, and next_action: retry_later.

Status decides the advice

The mapping has a branch for this code that reads the status. At 500 and above it says retry later. Below 500 it flips to retryable: false and fix_input. The factory always builds a 502, so in practice you see the retryable form, but a client that reads the flag handles both without change.

provider_submission_failed in the actionability mapping (Sume API source, read 2026-10-05)
FieldStatus 5xxStatus below 500
category / stageruntime_unavailable / generation_submitruntime_unavailable / generation_submit
retryabletruefalse
retry_after_secondsserver value, else 30null
public_reasongeneration_submit_failedgeneration_submit_failed
next_actionretry_laterfix_input

Not every 502 is this one

A different 502 tells you your own input was unreachable, such as a media URL that Sume could not download, and that one is retryable: false with fix_input. The status is the same and the advice is the opposite, which is why a handler must branch on error.code and retryable, as the related posts show. Here nothing is wrong with the request: the job just did not start.

Retry safely

Use the same Idempotency-Key, honor the delay and cap the attempts:

import json, time

BODY = '{"error": {"code": "provider_submission_failed", "retryable": true, "retry_after_seconds": 30}}'

def next_delay(err: dict, attempt: int, cap: int = 4):
    if not err["retryable"] or attempt >= cap:
        return None
    base = err.get("retry_after_seconds") or 30
    return base * (2 ** min(attempt, 2))

print(next_delay(json.loads(BODY)["error"], 0), next_delay(json.loads(BODY)["error"], 4))
time.sleep(0)

Why the delay defaults to 30 seconds

The mapping uses a server-supplied retry_after_seconds if there is one and 30 otherwise. Treat that number as a floor, not a schedule, and add jitter when many workers fail together, so they do not all return at the same second. Because the job never started, retrying does not double the work: the same Idempotency-Key returns the job if it did start after all, and creates it if it did not.

What to check if it repeats

No job result exists, so read GET /v1/jobs/:id/events if the body carries a job, or the status_url in details when present. If three attempts fail, stop and send the request_id to support. The jobs and results guide shows how to recover a job by id.

A last practical point: log the code, the status and the attempt number on every try. When a run of failures is later reviewed, those three fields show whether the platform recovered after one retry or kept refusing, and whether your backoff was long enough. Do not log the API key or the full request body, and keep the request_id as the join key with support.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume