Sume SDK returns {data, error}, not exceptions: an unwrap helper

Generated @sume-com/sdk operations resolve with data, error and response instead of throwing. Wrap them in an unwrap helper that throws a typed error.

5 min readSume
All posts

Generated operations in @sume-com/sdk do not throw on an API error; they resolve with { data, error, response }. That is easy to miss inside a retrying task runner, where a swallowed error looks like success. One unwrap function that throws a typed error fixes it.

Which helpers do throw

The docs split the behavior: generated operations resolve with the triple, while subscribeFormatRun and waitForRun throw, because a poll loop has nowhere to put a non-result. So your code needs both a try/catch for the helpers and the unwrap for the generated calls.

The helper

The error body is the Sume envelope, with error.code and error.request_id, so the thrown error can carry both.

export class SumeError extends Error {
  constructor(
    public status: number,
    public code: string,
    message: string,
    public requestId?: string,
  ) {
    super(message);
  }
}

export function unwrap<T>(r: { data?: T; error?: any; response: Response }): T {
  if (r.error || r.data === undefined) {
    const e = r.error?.error ?? {};
    throw new SumeError(
      r.response.status,
      e.code ?? "unknown",
      e.message ?? "request failed",
      e.request_id,
    );
  }
  return r.data;
}

Then branch on the code

With a thrown SumeError, your retry layer can switch on code: retry rate_limited and provider_capacity_exceeded with the same idempotency key, stop on insufficient_credits, and fix the input on invalid_request.

Throw behavior in @sume-com/sdk (read 2026-10-03)
CallOn API error
Generated operationsResolve with data, error, response
subscribeFormatRun, waitForRunThrow
waitForJobThrows SumeJobRequestError or SumeJobTimeoutError

Sources

Related posts

More in Developers

All Developers posts

Written by Sume