Skip to main content

Error categories

When a request fails, kweri categorizes the error before caching it. The category determines whether the error is retryable:

HTTP errors throw by default

The built-in fetcher throws on any non-2xx response, so 4xx/5xx are treated as errors out of the box — your catch runs and hooks expose isError. The thrown error carries the parsed body and status:
This means a failed request rejects — code after await mutateAsync(...) won’t run on a 4xx/5xx. If you supply your own fetcher, you must re-add the res.ok check yourself; raw fetch does not reject on bad status.

Automatic retry

Retries only fire for errors marked retryable: true. The delay uses exponential backoff with jitter:
Configure the maximum number of retries on the Kweri instance:
Setting maxRetries to 0 disables retries entirely. The default is intentionally conservative — enable retries explicitly for your use case.

Error caching

Errors are cached for a short window (default 5 seconds). During this window, subsequent calls to kweri.query() for the same key return the cached error immediately rather than hammering the server. After the error cache expires, the next query call fires a fresh request.

Accessing errors in hooks

ValidationError

ValidationError is thrown when the server response doesn’t match the endpoint’s response schema — i.e. a contract mismatch between your definition and what the server actually returned:
ValidationError is not retryable.
Params are not validated at runtime. The endpoint params schema drives TypeScript type inference only. Passing wrong params is a compile-time error, not a runtime one.

Custom error handling with a custom fetcher

The default fetcher already throws on non-2xx. You only need a custom fetcher for non-standard error shapes — e.g. an API that returns { error: '...' } with a 200 status. If you write one, keep the res.ok check (raw fetch won’t reject on its own):