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 or upload reuses the same Idempotency-Key, so it never starts or bills a second job.
RetryPolicy is a frozen dataclass:
| Field | Type | Default | Description |
|---|---|---|---|
max_retries | int | 2 | Retries after the first attempt. 0 disables retries. |
backoff_initial | float | 0.5 | First delay in seconds, doubled on each retry. 0 disables backoff. |
backoff_max | float | 5.0 | Longest delay in seconds. 0 disables backoff. |
backoff_jitter | float | 0.25 | Fraction of each delay randomly taken off, from 0 to 1. |
http_statuses | set[int] | {408, 429, 500, ..., 599} | Statuses that are retried. |
respect_retry_after | bool | True | Wait what retry-after-ms or retry-after says instead of the backoff. |
api_connection_error | bool | True | Retry NaceAPIConnectionError. |
api_timeout_error | bool | True | Retry NaceAPITimeoutError. |
exceptions | set[type[BaseException]] | set() | More exception types to retry. |
predicate | Callable[[BaseException], bool] | None | None | Called with each error; True retries it too. |
timeout | float | None | 30.0 | Total budget in seconds for one call: every attempt plus the waits between them. None removes it. |
The budget counts from the first attempt. Before each retry the client adds the wait to the time already spent, and if that reaches timeout, it stops and raises the last error. So with the defaults, an attempt that fails after 30 seconds or more is not retried: a request that runs into the 60-second timeout, or a 529 that came after Drex's 55-second wait for the model. A retry-after longer than what is left of the budget isn't waited out either: the error is raised at once. To retry those, raise the budget above your timeout:
from nace_sdk import NaceClient, RetryPolicy
client = NaceClient(timeout=60, retry=RetryPolicy(max_retries=3, timeout=200))A retry= on one call replaces the client's policy for that call. The client doesn't expose its policy, so build one from the policy you passed to the client (or from RetryPolicy()) with dataclasses.replace(policy, max_retries=0). A negative max_retries, a negative or infinite delay, a jitter outside 0 to 1, or a nonpositive timeout raises NaceError. Retried attempts carry an X-Nace-Retry-Count header. The job event stream and a download cut off midway are never retried, and saved-schema creates aren't retried unless you pass retry; see Progress events, Download a file and Saved schemas.