timeline_get 409 job_not_completed on Sume MCP: retry, do not give up

A 409 job_not_completed from timeline_get means the render is still running, so retry. Call jobs_wait on the same job_id; never report the run blocked.

4 min readSume
All posts

On Sume's hosted MCP, timeline_get returning 409 job_not_completed means the render is still running. It is retryable and never terminal: call jobs_wait on the same job_id with timeout_seconds between 45 and 55, and repeat until the job is terminal.

What the next steps say

The tool's built-in next steps are explicit. First, 409 job_not_completed means still rendering, retryable, never terminal, and an agent must never report blocked on it. Second, do not hand-poll; use jobs_wait on the same job and repeat that wait until the job is terminal or you have waited at least ten minutes in total. Third, deliver video_url and treat structured warnings[] as soft degradations, not hard failures.

Reading timeline_get states on Sume MCP (read 2026-10-05 against the Sume codebase)
ObservedMeaningAction
409 job_not_completedstill renderingjobs_wait on the same job_id
wait slice with timed_out trueyour window closed, job continuesre-issue jobs_wait
success with warnings[]soft degradationdeliver video_url, mention warnings
status failedterminalread jobs_get, then see the recovery code

Do not mix the two 409s

jobs_result also answers 409 job_not_completed, but on a failed job it means something else: the job is over and has no result, so read jobs_get. For timeline_get the same status on a running job means wait. Decide using the job status, not the HTTP code alone. The jobs_wait post covers slice sizes.

A loop that follows the contract

The sketch below uses a stand-in for the wait call so it runs as written.

import time

def wait_until_done(wait, job_id, budget_s=600, slice_s=50):
    start = time.monotonic()
    while time.monotonic() - start < budget_s:
        res = wait(job_id, slice_s)
        if res.get('terminal'):
            return res
    raise TimeoutError('still rendering after budget; do not report blocked')

fake = iter([{'terminal': False}, {'terminal': True, 'status': 'completed'}])
print(wait_until_done(lambda j, s: next(fake), 'job_1', budget_s=5))

Limits

Ten minutes is the contract's minimum wait before escalating, not a promise about render time. If the budget passes, tell the user the render is still running and offer to check again; that is accurate, whereas claiming failure is not.

Why the long tail matters

Most renders finish quickly, but the tail is the case that matters. A render that had to retry is also the one carrying work nobody wants to pay for twice. The server's own comment records an incident where two polls 90 seconds apart both returned 409, the run was declared blocked, and the render finished 80 seconds later. A finished deliverable sat unused for a day.

Checklist before you ship

  • Treat 409 job_not_completed on timeline_get as still rendering.
  • Wait with jobs_wait on the same job_id at 45 to 55 seconds per slice.
  • Keep waiting for at least ten minutes in total before escalating.
  • Deliver video_url and surface warnings as soft degradations.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume