Seedance and Kling submit errors: which to retry and which to fix

A Sume video submit can fail with 402, 429 queue_full, 429 rate_limited or 400. Which to retry with the same key and which need a changed request.

5 min readSume
All posts

Retry 429 rate_limited and 429 queue_full with backoff and the same Idempotency-Key. Fix 402 insufficient_credits by adding balance first, and fix any 400 or 404 by changing the request, since resending the same body gets the same answer. That is the whole decision tree for a Seedance or Kling submit on Sume.

The details matter because the three look alike in logs. The rules below come from Sume's errors page and generation admission docs.

Which submit errors are worth retrying?

429 queue_full means your processing slots and the waiting queue are both full. Poll existing jobs, wait until one finishes, and retry. 429 rate_limited is request-volume protection and also clears with backoff. In both cases, reuse the same Idempotency-Key: if the first attempt actually created a job, you get that job back, not a second paid one.

A 5xx or a network timeout is ambiguous, because the job may have been created. Retry with the same key for the same reason.

Which errors need a different request?

402 insufficient_credits fires before any provider work, when Sume cannot reserve the estimated cost. Retrying without topping up fails again. A 400 validation error names the field. Typical Seedance and Kling causes are reference_*_urls sent to kling-3, bitrate_mode on a model that rejects it, a duration outside the model's range, or first_frame and references mixed together. An unknown model id is 404 model_not_found.

Use a fresh Idempotency-Key whenever you change the body, since a key identifies one intended request.

What does the full table look like?

Group by the action your client should take.

Video submit errors and the right reaction, read 2026-10-02
ResponseRetry same request?Action
429 queue_fullYes, with backoffPoll existing jobs, then resubmit with the same key
429 rate_limitedYes, with backoffSlow down request volume
402 insufficient_creditsNoTop up, then resubmit
400 validation errorNoFix the named field; new key for a changed body
404 model_not_foundNoUse an id from GET /v1/videos/models
5xx or timeoutYesSame key, bounded attempts

How do I encode it in a client?

This submit helper retries only the retryable codes, up to five times, and reuses one key across attempts.

import os, time, uuid, requests

def submit(body: dict, tries: int = 5) -> dict:
    key = str(uuid.uuid4())
    h = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}",
         "Idempotency-Key": key}
    for n in range(tries):
        try:
            r = requests.post("https://api.sume.com/v1/videos",
                              json=body, headers=h, timeout=60)
        except requests.RequestException:
            time.sleep(2 ** n)
            continue
        if r.status_code == 429 or r.status_code >= 500:
            time.sleep(2 ** n)
            continue
        r.raise_for_status()  # 400, 402, 404: fix the request
        return r.json()
    raise RuntimeError("gave up after retries")

if __name__ == "__main__":
    print(submit({"model": "seedance-2-mini", "prompt": "A paper boat"}))

What about jobs that fail after they were accepted?

That is a different path. An accepted job that ends failed releases or refunds its reservation where applicable, and its error text is on the poll response. Do not resubmit blindly: read GET /v1/jobs/{id}/events first, since an unreachable input URL or a refused reference will fail the same way again. See video job concurrency and queueing for how pending jobs behave.

The helper uses exponential delay because Sume's docs, as read for this post, do not specify a retry interval for submit errors.

How should I log these so they are debuggable?

Log the HTTP status, the error.code, the model id and the idempotency key for every submit, and nothing from the prompt you would not want in a log. The code is the reliable field: statuses are shared, codes are stable. When you contact support, the request id from the response is the quickest handle.

Alert on a rising rate of queue_full rather than on any single occurrence. A steady trickle means your batch is larger than your plan's processing and queue capacity allow, and the fix is pacing, not retries. A spike of 400 after a deploy usually means a field was added to a request that a specific model rejects.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume