Sume SDK 402 insufficient credits: it is returned, not thrown

Generated Sume SDK calls resolve with data, error and response. Turn a 402 into SumeInsufficientCreditsError with toSumeApiError and stop retrying.

4 min readSume
All posts

How do I catch a 402 from the Sume SDK?

You do not catch it, because generated operations such as generateVideoV1 resolve with { data, error, response } and never throw on an HTTP error. Read error, pass its status and body to toSumeApiError, and test the result with instanceof SumeInsufficientCreditsError.

A 402 means the workspace balance cannot fund the estimate that Sume reserves at submit. Nothing ran and nothing was charged. The only fix is to add funds, so a retry loop is wasted effort: the same request returns the same answer until the balance changes.

Which error class means what

toSumeApiError builds a typed error from the envelope every /v1/ failure returns. It keeps code, retryable, retryAfterSeconds and nextAction, so you branch on fields and not on message text.

Typed errors in @sume-com/sdk and the response to each (read 2026-10-06)
StatusSDK classWhat to do
402SumeInsufficientCreditsErrorStop, add funds, then resubmit
429SumeRateLimitErrorWait for retryAfterSeconds, same key
409SumeConflictErrorDo not retry; read the code
5xxSumeServerErrorRetry later with the same key

Branch on the typed error

This submit helper returns the job id or throws a class you can handle. The check on nextAction is informational: for a 402 the envelope names add_funds.

import {
  createSumeClient, generateVideoV1, toSumeApiError,
  SumeInsufficientCreditsError, SumeRateLimitError,
} from "@sume-com/sdk";

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

export async function submit(orderId, prompt) {
  const { data, error, response } = await generateVideoV1({
    client,
    headers: { "idempotency-key": `order-${orderId}` },
    body: { prompt, mode: "async" },
  });
  if (!error) return data.data.request_id;
  const err = toSumeApiError(response?.status, error, "submit failed");
  if (err instanceof SumeInsufficientCreditsError) {
    console.error("out of credits:", err.nextAction, err.requestId);
  } else if (err instanceof SumeRateLimitError) {
    console.error("rate limited, wait", err.retryAfterSeconds, "s");
  }
  throw err;
}

Check the balance before a batch

GET /v1/balance returns the balance and GET /v1/usage is the ledger. Sume reserves the provider list price times 1.25 for each job at submit, so a batch of 30 second clips can fail on its fifth submit when the balance only covered four. Read the balance first, compare it with your own estimate, and submit only what the balance funds.

Log requestId from the typed error, so a failed submit can be traced later.

Keep the handler small: one place converts the raw error into a typed error, and the rest of your code branches on the class. That keeps a 402 from being retried by a generic catch-all, and it keeps a 429 from being reported to a customer as a failure when a short wait would have fixed it. A job that never started also has no result to clean up, so on a 402 you only need to tell the person who owns the account that funds are needed.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume