createSumeClient timeout is 10 minutes per request: tune it for polls

The Sume SDK client waits up to 10 minutes on each HTTP request, so one hung status poll can stall waitForJob for 10 minutes. Use a short-timeout client.

5 min readSume
All posts

createSumeClient from @sume-com/sdk@0.2.0 sets a per-request timeout of 10 minutes by default (timeout: 600000). That is the limit on one HTTP request, not on a job, and it is far too long for a status poll. If a poll connection hangs, waitForJob sits there for up to 10 minutes before the request aborts, no matter what deadline you gave the wait itself. For polling, build a client with a short timeout, such as 30 seconds, and keep a separate client for submits.

Pass timeout: 0 to disable the per-request limit entirely. That is rarely what you want. The SDK run helpers page documents the job and run deadlines, which are separate numbers: 20 minutes for waitForJob, 10 minutes for waitForRun, and 20 minutes for subscribeFormatRun.

Three clocks that are easy to confuse

A wait has three independent timers. The request timeout bounds one call and applies afresh to each retry attempt. The wait timeout bounds the whole loop. The server-side bounded wait on a submit with mode: "sync" or "subscribe" is capped at 30 seconds and describes how long the API holds the HTTP request open, not how long the job may run (Jobs and results).

The practical consequence is a floor. A client used for a sync submit needs a request timeout comfortably above 30 seconds, or it will abort a request the server is still holding open. A client used only for polls and status reads can be much stricter.

Timers in a Sume SDK wait (SDK source and docs, read 2026-10-04)
TimerDefaultWhat it bounds
Client timeout option10 minutesOne HTTP request, reset per retry attempt
waitForJob timeout20 minutesThe whole poll loop for a job
waitForRun timeout10 minutesThe whole poll loop for a run
Server sync and subscribe wait30 seconds maxHow long a submit request is held open

Two clients, two budgets

The snippet gives polls a 30-second request limit and submits 60 seconds, then waits with the poll client. A caller-supplied signal is combined with the timeout, so aborting your own signal still cancels the in-flight request immediately, and an abort you cause is never retried.

import { createSumeClient, generateImageV1, waitForJob } from "@sume-com/sdk";

const apiKey = process.env.SUME_API_KEY ?? "";
if (!apiKey) throw new Error("set SUME_API_KEY");

const submitClient = createSumeClient({ apiKey, timeout: 60_000 });
const pollClient = createSumeClient({ apiKey, timeout: 30_000, maxRetries: 2 });

const { data, error } = await generateImageV1({
  client: submitClient,
  headers: { "idempotency-key": crypto.randomUUID() },
  body: { prompt: "Matte black bottle on marble, soft window light", mode: "async" },
});
if (error || !data) throw new Error(JSON.stringify(error));

const job = await waitForJob(data.data.request_id, {
  client: pollClient,
  signal: AbortSignal.timeout(15 * 60_000),
});
console.log(job.status);

What not to change

  • Do not set the request timeout to match the job length. A request is one poll, and a ten-minute job is hundreds of short polls.
  • Do not retry a submit without an Idempotency-Key. The client only replays a POST that carries one, so a timeout on a keyless submit is surfaced to you instead.
  • Keep maxRetries at 2 or higher for polls, since read failures are the case retries exist for.
  • Treat a timeout on a submit as unknown outcome: read your job list or retry with the same key rather than submitting again with a new one.

Related posts

More in Developers

All Developers posts

Written by Sume