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:

FieldTypeDefaultDescription
maxRetriesnumber2Retries after the first attempt. 0 turns retries off.
backoffInitialMsnumber500The first wait, doubled for each retry up to backoffMaxMs.
backoffMaxMsnumber5000The longest backoff wait.
backoffJitternumber0.25The fraction of each backoff wait taken off at random, from 0 to 1.
httpStatusesReadonlySet<number>408, 429 and 500 to 599Statuses to retry. A set you pass replaces this one. An error whose body says "retryable": false is never retried.
respectRetryAfterbooleantrueWait what retry-after-ms or retry-after asks, instead of the backoff.
maxRetryAfterMsnumber60000The longest server delay to honor. A longer one falls back to the backoff.
apiConnectionErrorbooleantrueRetry an APIConnectionError.
apiTimeoutErrorbooleantrueRetry an APITimeoutError.
timeoutMsnumber | nullnullThe 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: a maxRetries that 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-Count header.
  • 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.create and createVersion (see Saved schemas), workspaces.create, and domains.create, publish and duplicate.

On this page