Errors and utilities
Retries
The client retries 408, 429 and 5xx responses, dropped connections and timeouts, with exponential backoff, and honors retry-after-ms and retry-after. It doesn't retry an error whose body says "retryable": false. Every retry of a document create reuses the same Idempotency-Key, minted once per call, so it never starts or bills a second job.
RetryPolicy has these fields:
| Field | Type | Default | Description |
|---|---|---|---|
maxRetries | number | 2 | Retries after the first attempt. 0 turns retries off. |
backoffInitialMs | number | 500 | The first wait, doubled for each retry up to backoffMaxMs. |
backoffMaxMs | number | 5000 | The longest backoff wait. |
backoffJitter | number | 0.25 | The fraction of each backoff wait taken off at random, from 0 to 1. |
httpStatuses | ReadonlySet<number> | 408, 429 and 500 to 599 | Statuses to retry. A set you pass replaces this one. An error whose body says "retryable": false is never retried. |
respectRetryAfter | boolean | true | Wait what retry-after-ms or retry-after asks, instead of the backoff. |
maxRetryAfterMs | number | 60000 | The longest server delay to honor. A longer one falls back to the backoff. |
apiConnectionError | boolean | true | Retry an APIConnectionError. |
apiTimeoutError | boolean | true | Retry an APITimeoutError. |
timeoutMs | number | null | null | The retry budget: no retry starts once the time since the call began, plus the next wait, would reach it. It doesn't cut a running attempt short. null removes it. |
The time budget
The default timeoutMs=null disables the total retry budget. A slow retryable failure, including a timeout or a 529 after Drex's 55-second model deadline, can use the remaining retries. The default permits three attempts in total, so slow failures can take several minutes to surface, including waits.
An explicit timeoutMs counts from the first attempt. Before each retry, the client adds the next wait to the time already spent; if that reaches the budget, it raises the last error. This check decides whether another attempt starts; it does not interrupt an attempt or enforce a hard deadline for the whole call.
Each attempt still uses the client's HTTP timeout (60 seconds by default).
// Opt into a retry budget; long failures may consume it before any retry.
const client = new NaceClient({ retry: { timeoutMs: 30_000 } });A policy for one call
A retry you pass to the client or to one call is merged over the policy beneath it, so name only the fields you change:
const job = await client.documents.parse(
{ source: "https://example.com/report.pdf" },
{ retry: { maxRetries: 0 } },
);What else to know
- An invalid policy throws a
NaceError: amaxRetriesthat isn't a whole number of 0 or more, a negative wait or budget, a jitter outside 0 to 1, or a status outside 100 to 999. - Retried attempts carry an
X-Nace-Retry-Countheader. - Never retried:
jobs.events. See Progress events. - Not retried unless you pass
retry, since a retry after the first call landed would save something twice or fail:extractionSchemas.createandcreateVersion(see Saved schemas),workspaces.create, anddomains.create,publishandduplicate.