Error Handling Patterns
Problem
HTTP errors (4xx, 5xx), network failures, and timeouts need different recovery strategies. You want consistent handling across all call sites without repeating the same try/catch branches.
Solution
Use the specific error classes (AbortError, TimeoutError, NetworkError, HttpError) to narrow by failure mode, and shouldRetry on createQuery() or createMutation() to customize retry behavior.
Status-code branching
ts
import { AbortError, HttpError, TimeoutError } from '@vielzeug/courier';
try {
await api.get('/users/1');
} catch (err) {
if (err instanceof AbortError) return; // user canceled
if (err instanceof TimeoutError) return toast.error('Request timed out');
if (HttpError.is(err, 404)) return null;
if (HttpError.is(err, 401)) return redirectToLogin();
if (HttpError.is(err, 403)) return showForbidden();
if (HttpError.is(err)) throw new Error(`Unexpected ${err.status}: ${err.url}`);
throw err; // re-throw non-Courier errors
}Global error logger
ts
const api = createApi({ baseUrl: 'https://api.example.com' });
api.use(async (ctx, next) => {
try {
return await next(ctx);
} catch (error) {
Sentry.captureException(error, {
extra: { method: ctx.init.method, url: ctx.url },
});
throw error;
}
});Mutation error state
ts
const mutation = createMutation((input: number, signal: AbortSignal) => api.delete(`/users/${input}`, { signal }));
mutation.subscribe((state) => {
if (state.status === 'error') {
// State is observable — no need for try/catch in UI
toast.error(state.error!.message);
mutation.reset();
}
});
mutation.mutate(1).catch(() => {}); // error is surfaced via state, not thrownPitfalls
- Courier throws distinct classes for each failure mode —
HttpError(has a response),NetworkError(no response),TimeoutError, andAbortError. Catching onlyHttpErrormisses connection failures. - A
500response with a JSON error body throwsHttpError, not a genericError. Do not useinstanceof Erroralone to detect HTTP failures. - Retrying on all errors wastes resources on 401 (wrong credentials) or 422 (validation failure). Limit retries to
NetworkErrorandHttpErrorwith status ≥ 500.