Sume jobs_wait outcome: wait_slice_expired is not a failed job
jobs_wait returns outcome terminal, wait_slice_expired or operator_stopped. Only terminal means the jobs ended; an expired slice says nothing about the jobs.

The outcome field on a Sume jobs_wait result has three values: terminal, wait_slice_expired and operator_stopped. Only terminal means the waited-for jobs reached a final state. wait_slice_expired means your polling window closed first and says nothing about the jobs, which keep running and stay billed.
Why `timed_out` was not enough
timed_out: true is a scheduling fact about the caller's window. Agents read it as a verdict. The outcome field was added so the ending is named explicitly, and a timed-out result carries guidance in the same object the model is reading when it decides. The guidance for an expired slice is blunt: any job still queued or processing is billed and will reach a terminal state on its own, so re-issue jobs_wait with the same ids, and proceeding without those ids produces a deliverable missing what they were generating.
| outcome | Meaning | What to do |
|---|---|---|
| terminal | every waited-for job reached a terminal state | read each job status, then jobs_result for the successes |
| wait_slice_expired | the polling window closed first | re-issue jobs_wait on the same ids |
| operator_stopped | operations stopped at least one job | stop polling it; wait on pending ids only |
Why the slice is short
One jobs_wait call holds a single request open and sends nothing until it answers, so the edge in front of the API bounds it. Remote HTTP clamps the hold to 55 seconds, and an omitted timeout_seconds defaults to 50 there. A longer ask is accepted and clamped, and the result says so. The clamp comparison shows how client timeouts interact.
Loop on outcome
This loop stops only on a terminal outcome. The wait function is a stand-in so it runs as written.
def wait_all(wait, ids, max_slices=40):
for _ in range(max_slices):
res = wait(ids)
if res['outcome'] == 'terminal':
return res
if res['outcome'] == 'operator_stopped':
ids = res.get('pending_job_ids', [])
if not ids:
return res
raise TimeoutError('still running; tell the user, do not ship partial output')
seq = iter([{'outcome': 'wait_slice_expired'}, {'outcome': 'terminal'}])
print(wait_all(lambda i: next(seq), ['job_a']))Limits
Slice counts are your budget, not Sume's. If your own deadline arrives first, report the jobs as still running with their ids; do not call them failed.
A real failure pattern
A production run read two consecutive 55-second batches with timed_out: true, plus two 409 reads, as a sign that a B-roll layer was not coming. It assembled a talking-head-only video and marked the run complete. Both clips finished minutes later, billed and unused. The loudest field in the response had been about the caller's polling window; the field that mattered was that the jobs were still in progress and not terminal.
Checklist before you ship
- Branch on outcome, with timed_out as a hint only.
- Never assemble a deliverable from a batch that still has pending ids.
- Keep the full id list and re-issue the same wait.
- Treat a job as failed only when its own status says failed.
Sources
Related posts
More in Developers
- jq one-liners for the video model catalog: ids, durations, 1080p
Two jq filters over GET /v1/videos/models: a table of ids with min and max seconds, and a filter for models that take 20 s at 1080p. Tested on a local copy.
- Kling motion control: output length follows the motion video
In Sume's Kling 3.0 motion control, duration_seconds (1-30) only sets the reservation. The motion video sets the output length. Price: $0.1575 a second.
- Kling motion control webhook_url: a Python receiver that verifies
Send mode async plus webhook_url on a Kling motion control submit, then verify x-sume-webhook-signature (HMAC SHA-256 over timestamp.body) in Python.
- Last frame of an Omni clip: fixing frame_time_out_of_range
Asking Sume video-frames for t equal to the clip length fails with frame_time_out_of_range. Take the last frame at duration minus a frame, in Python.
Written by Sume