Avatar sync wait: timed_out vs capacity_exhausted, and what to do

A sync avatar submit can return 2xx with sync.timed_out or sync.capacity_exhausted true. Both mean keep the job: poll status_url, never submit a new paid job.

4 min readSume
All posts

If a sync avatar submit returns a 2xx with sync.timed_out or sync.capacity_exhausted set to true, the job exists and is still running. Poll status_url and do not submit a new paid job for the same intent. If you must retry the submit itself, send the same Idempotency-Key and you get the original job back.

What the two flags mean

Sume clamps wait_timeout_seconds to 0-30. That sets how long the HTTP request may block, not how long the job takes. Avatar-video jobs usually take longer than 30 seconds, so a sync submit often ends before the job does. The response is still a 2xx and still carries the job id, because the end of the wait budget is not an admission failure.

Sync envelope flags on avatar submits (Sume jobs docs, read 2026-10-05)
FlagMeaningYour next step
sync.timed_out trueWait ended before a terminal stateGET status_url, obey next_poll_after_seconds
sync.capacity_exhausted trueSume skipped the wait; waiter budget of the process was fullSame: poll, do not resubmit
sync is nullMode was async or webhookNormal polling or webhook
Terminal result in bodyJob finished within the waitRead the result

Handle it in code

Branch on the envelope and not on the HTTP status. A 2xx without a terminal state is not a failure and not a success; it is an in-flight job. The docs recommend async or webhook for work that can last longer than 30 seconds, and say that sync stays supported.

def next_step(envelope):
    sync = envelope.get("sync") or {}
    if envelope.get("terminal"):
        return "fetch" if envelope.get("result_ready") else "inspect_events"
    if sync.get("timed_out") or sync.get("capacity_exhausted"):
        return "poll " + envelope["status_url"]
    return "poll " + envelope["status_url"]

print(next_step({"terminal": False, "status_url": "/v1/jobs/x/status",
                 "sync": {"timed_out": True}}))

Why not just raise the timeout

You cannot: the API clamps the wait at 30 seconds. A client-side timeout, which can be minutes, is the right place for a longer deadline, and the docs state that a client timeout does not cancel the job. The job keeps running and keeps billing, so store the id and read it again later, or cancel it explicitly if you no longer need it.

A worked timeline

Suppose you submit a 40-second avatar script in sync mode with a 30-second wait. At second 30 the request returns a 2xx with sync.timed_out: true, a status_url, and often a next_poll_after_seconds. Your code stores the id, sleeps for the suggested interval, and reads the status. It sees processing, sleeps again, and eventually sees completed with next_action: fetch_result. At no point did you pay for a second job, and at no point did you need to guess.

The same timeline holds when the waiter budget is full: the call returns at once with capacity_exhausted: true and no wait at all. If your code treats an immediate return as a failure and retries in a loop, you will hammer the API for no gain, so handle both flags the same way.

Checklist

  • Always store avatar_video_id and status_url before you wait.
  • Use async plus polling for avatar renders, or a webhook for terminal events.
  • Reuse the same Idempotency-Key for an exact retry of the submit.
  • Do not treat capacity_exhausted as queue_full; they are different conditions, and only queue_full is a rejection.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume