Sume SDK error code unknown_error and a null requestId
When the response body is not a Sume error envelope, the SDK falls back to code unknown_error with no request id. What it means and what to log instead.

An SDK error with code: "unknown_error" and requestId: null means the response body was not a Sume error envelope. Real API errors always carry error.code and a request id. An HTML page from something in front of the API, an empty body or plain text has neither, so the SDK invents the code unknown_error rather than throwing a second error while reporting the first. Treat it as a transport-level failure and decide on the HTTP status alone.
What does the fallback set?
The envelope the API returns is an error object with code, message, request_id, retryable, retry_after_seconds, next_action and details. The SDK's toSumeApiError reads those when they exist. When the body fails the check (an object whose error.code is a string), it builds a bare SumeApiError instead.
| Field | Real Sume envelope | Non-envelope body |
|---|---|---|
| code | The server's token, such as rate_limited | unknown_error |
| requestId | From error.request_id | null |
| retryable | The server's own verdict when present | true for 408, 429 and 5xx, else false |
| retryAfterSeconds | From error.retry_after_seconds | null |
| nextAction | From error.next_action | null |
| body | The parsed envelope | Whatever the body was |
Where do I find the request id then?
Every response from the API carries x-sume-request-id, and the same value is in the envelope. If your logs show unknown_error, the response most likely never reached the API's error handler, so look at the response headers you captured: a missing x-sume-request-id on a 5xx points at a layer in front of the API (a corporate proxy, a load balancer or a CDN rule). If the header is present, quote it in your support request along with the run id.
Do not paste API keys, signing secrets or raw media URLs into the ticket. Only the request id and the error code are needed.
Should I retry an unknown_error?
The fallback sets retryable from the status alone, which is the right default: a 502, 503 or 504 is worth another attempt, and a 400 or 404 is not. For a read, retrying is always safe. For a run create, retry only with the same Idempotency-Key, because without a key a replay would start and bill a second run. createSumeClient already applies that rule: it retries a POST only when an Idempotency-Key header is present, and subscribeFormatRun generates one unless you pass your own.
import { SumeApiError } from "@sume-com/sdk";
export function describe(error: unknown) {
if (!(error instanceof SumeApiError)) return { kind: "not-sume" };
if (error.code === "unknown_error") {
// Not an API envelope: no request id to quote.
return { kind: "transport", status: error.status, retry: error.retryable };
}
return { kind: "api", code: error.code, requestId: error.requestId };
}How is this different from a Sume 5xx?
A Sume-side outage on a read, such as 503 studio_agent_upstream_unavailable, arrives as a proper envelope with a code, a request id and retryable. The run keeps executing in that case, and the docs say a 429 or 503 inside a poll loop is transient. unknown_error is the contrast case: the status tells you something failed, and nothing else in the body can.
What should I log for a support request?
For a real envelope, log code, requestId, the HTTP status and the run id. For unknown_error, add what the SDK cannot: the response headers you saw, the URL host you called, and the time. The documented rule for reports applies to both: include the request id when there is one, and never include API keys, signed URLs, raw media URLs or private workspace or user ids.
If the same call succeeds a minute later, the earlier failure was transient. If it keeps failing with a non-envelope body, check that baseUrl points at the API host and not at a web page: the SDK's default is https://api.sume.com, with https://api.dev.sume.com for development, and the CLI's SUME_API_BASE_URL carries a /v1 suffix that the SDK's baseUrl does not.
Sources
Related posts
More in Developers
- 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.
- instanceof SumeNotFoundError is false on a waitForRun 404
waitForRun and subscribeFormatRun throw SumeRunRequestError, not the 401-to-5xx subclasses. Branch on status or code instead; a working catch block.
- waitForJob throws SumeJobRequestError, not a SumeApiError
A catch for SumeApiError does not see failures from waitForJob. Why SumeJobRequestError has no code or requestId, and how to recover both with toSumeApiError.
- Where the Sume TypeScript SDK runs: Node 18+, Bun, Deno and Workers
@sume-com/sdk has no runtime dependencies and needs only fetch and WebCrypto. Install it, create a client, and know which options and helpers it adds.
Written by Sume