waitForRun timeout: why SumeRunTimeoutError can arrive early

The Sume SDK's waitForRun checks its deadline before it sleeps, so SumeRunTimeoutError can fire up to one poll interval early. The run keeps going.

5 min readSume
All posts

waitForRun in the Sume TypeScript SDK checks its deadline before it sleeps. If another poll interval would cross the deadline, it throws SumeRunTimeoutError right away instead of sleeping through it, so the error can arrive up to one poll interval before the timeout you passed. The run itself keeps going.

That behavior is described in Waiting for runs and jobs and visible in the SDK source. It matters if you assert on elapsed time in tests, or if you set a timeout close to your poll interval.

What exactly does the deadline check do?

On entry the helper computes deadline = now + timeout. After each non-terminal status read it asks one question: would the next sleep, now + pollInterval, reach the deadline? If yes it throws SumeRunTimeoutError carrying the runId and lastStatus. If not it sleeps with jitter and reads again.

The docs put the intent plainly: the deadline is checked before sleeping, not after, so a caller who asks for a 5 second timeout hears about it in about 5 seconds, rather than 5 seconds plus one whole poll interval. The cost of that choice is that the final window shorter than one interval is never used for another read.

waitForRun timing defaults (read 2026-10-03)
OptionDefaultEffect
timeout10 minutesDeadline for the whole wait
pollInterval2 secondsGap between status reads; also the early-exit window
signalnoneAborts the wait and the in-flight request; rejects with the signal's reason
maxTransientFailures6Consecutive failed reads tolerated

What does a short timeout look like?

With timeout: 5000 and the default 2 second interval, the helper reads, sleeps about two seconds, reads again, and so on. The read at roughly the four second mark sees that another sleep would pass the five second deadline, so it throws then. A timeout shorter than one interval throws after the first non-terminal read.

The snippet below shows the pattern with a run id you already hold. It catches the timeout and stores the last status instead of treating it as a failure.

import { createSumeClient, waitForRun, SumeRunTimeoutError } from "@sume-com/sdk";

const client = createSumeClient({ apiKey: process.env.SUME_API_KEY! });

export async function check(runId: string) {
  try {
    return await waitForRun(runId, {
      client,
      family: "format",
      timeout: 5_000,
      pollInterval: 2_000,
    });
  } catch (error) {
    if (error instanceof SumeRunTimeoutError) {
      // Still running. Nothing was cancelled.
      return { pending: true, runId: error.runId, lastStatus: error.lastStatus };
    }
    throw error;
  }
}

Does a timeout stop the run?

No. The docs repeat it in two places: a timeout does not cancel the run, which keeps going and keeps spending, and you have only stopped watching. Store the run id and read it later with getFormatRun, or cancel it with cancelFormatRun.

For a Format run the enforced deadline lives on the receipt as expires_at, so a better wait budget comes from that field than from a guess. The SDK's own comments say to use it to bound your own wait instead of inventing a timeout.

What about abort signals?

A signal aborts the wait and the in-flight request and rejects with the signal's reason, not with SumeRunTimeoutError. Branch on both: the timeout error means the budget ran out, an abort means your own code stopped. Neither says anything about the run's real status.

If you also want a hard cap beyond the helper's own deadline, pass AbortSignal.timeout(...) as in the docs example, and keep it longer than timeout so the helper's cleaner error wins.

Which helper has which default?

waitForRun defaults to 10 minutes. subscribeFormatRun, which creates and then waits, defaults to 20 minutes because video Formats routinely run 10 to 20. Pick a timeout from the Format's real runtime, and keep the poll interval at or below a fifth of it so the early exit costs you little.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume