Quota job error vs 402 insufficient_credits: where each appears

A 402 insufficient_credits means the submit was refused; a quota job category means an accepted job later failed. How to tell them apart and what to do next.

5 min readSume
All posts

A 402 insufficient_credits is returned by the submit request itself, before provider work starts, when the balance cannot cover the generation; a quota category appears on a job that already exists and failed. The first means fix the balance and resubmit, the second means read the job's public error metadata and follow its next action, which for quota is 'add funds or lower request cost' (read 2026-10-03).

When a 20-clip avatar batch stops halfway, knowing which one you hit tells you whether to top up, wait or change the request.

Four different 'no' answers

The errors docs separate status codes that look alike. 402 insufficient_credits is about money. 429 rate_limited is request volume and wants a back-off with the retry-after header. 429 queue_full means the workspace has no room for another paid job until one finishes or is canceled. And job-level categories such as quota, queue or generation_rejected describe what happened to a job after it was accepted.

Error signals, read 2026-10-03
SignalWhereMeaningNext step
402 insufficient_creditsSubmit responseBalance cannot cover the generationTop up, resubmit with same key
429 rate_limitedSubmit or read responseToo many requests in the windowBack off, honour retry-after
429 queue_fullSubmit responseConcurrency plus queue capacity fullWait for a job to finish, retry
Job category quotaFailed jobFunds or cost problem on an accepted jobAdd funds or lower request cost

Handling them in a batch

For a batch, treat each signal differently. A 402 should stop the whole batch and notify a human, because every later submit will fail the same way. A rate_limited should pause only briefly. A queue_full should hold the remaining items and retry them as jobs complete. A failed job should be inspected individually: look at its category, stage, retryability and next action, and only retry when the metadata says it is safe.

Always retry with the same Idempotency-Key for the same intent. Reusing a key with a different payload returns a conflict, which protects you from accidentally paying twice.

import asyncio

def next_step(status: int, code: str) -> str:
    if status == 402:
        return "stop batch, top up balance, resubmit with same key"
    if status == 429 and code == "queue_full":
        return "hold remaining items until a job finishes"
    if status == 429:
        return "sleep for retry-after seconds"
    return "inspect error.details and request_id"

async def main() -> None:
    for pair in [(402, "insufficient_credits"), (429, "queue_full"), (429, "rate_limited")]:
        print(pair, "->", next_step(*pair))

asyncio.run(main())

What to log

Log the request id from the error body alongside your own batch id. The docs say the request id is safe to share with Sume support, and you should never include API keys, signed URLs or raw media URLs in a report. With that one id, a support engineer can find the exact failure without asking you to reproduce it.

A concrete example

Imagine you queue 20 Plus clips of 30 seconds, a planned $147.00, with a balance of $120. The first 16 submits succeed. The seventeenth returns a 402 because the reservation for another $7.35 cannot be covered. The right response is to stop, top up, and resubmit clips 17 to 20 with the same keys. Clips 1 to 16 are unaffected and continue processing.

Now imagine a different failure: a job that was accepted, then fails during processing and shows the quota category. Open the job, read its public reason and next action, and follow it. Do not simply resubmit a new job with a new key, because that would be a second paid attempt for the same intent.

The idempotency rule that ties it together

Whichever signal you meet, the retry rule is the same: reuse the original Idempotency-Key for the same operation and payload. The docs warn that retrying unsafe submit requests without a key is not safe, and that reusing a key with a different payload gives a conflict. That protects a batch that stops at item 17 from creating a duplicate of item 16 on the way back in.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume