Skip to main content

Handling errors

Every error derives from FinesseError. HTTP errors carry the status, the message, a machine-readable code (branch on this, not on the message), how long to wait when the service asks you to, the remaining billing balance, and the request ID.
The API’s own error codes are listed in Errors.

Retries

Failed requests are retried twice with exponential backoff, honouring Retry-After: connection errors, timeouts, 408, 429 and 5xx. Calls that create something or cost credits (speech.create, voices.create, voices.clone, voices.enroll) send an Idempotency-Key, the same one on every retry, so the service runs them at most once. A retry of a clone that already succeeded gets the first result back, and a retried synthesis is served from the cache at no charge. If the first attempt is still running, the SDK waits for it (up to the request timeout) without using up a retry. speech.stream has no key, so it is only retried when the server certainly did no work: the connection never opened, 429, 502 or 503.
To choose the idempotency key yourself, pass an Idempotency-Key header on the call: { headers: { "Idempotency-Key": "..." } }.

Timeouts

Requests time out after 120 seconds. Synthesis on a cold engine can take a while to start, so keep this generous. For streams, the timeout is the longest wait between chunks, not the whole stream. A timeout throws APITimeoutError.

Request IDs

Every response has an X-Request-Id, and errors carry it. Quote it when you contact support.