Error Handling
All HTTP errors from HttpClient are wrapped in HttpClientError, a custom error class that includes the HTTP status code when applicable.
Basic Error Handling
Section titled “Basic Error Handling”import { HttpClient, HttpClientError } from '@http-client-toolkit/core';
const client = new HttpClient({ cache: new InMemoryCacheStore() });
try { const data = await client.get('https://api.example.com/user/1');} catch (error) { if (error instanceof HttpClientError) { console.log(error.message); // Error description console.log(error.statusCode); // HTTP status code (e.g. 404, 500) console.log(error.data); // Parsed response body (if any) console.log(error.headers); // Response headers }}Custom Error Handler
Section titled “Custom Error Handler”Use errorHandler to convert HTTP errors into your own domain types. The handler receives a typed HttpErrorContext with the response status, parsed body, and headers — no casting required.
errorHandler is only called for HTTP errors (non-2xx responses). Network failures and other non-HTTP errors are always wrapped in HttpClientError by the toolkit.
import { HttpClient, type HttpErrorContext } from '@http-client-toolkit/core';
class NotFoundError extends Error { constructor(message: string) { super(message); this.name = 'NotFoundError'; }}
class ApiError extends Error { constructor( message: string, public statusCode: number, ) { super(message); this.name = 'ApiError'; }}
const client = new HttpClient(stores, { errorHandler: (context) => { console.error(`Request to ${context.url} failed`);
if (context.response.status === 404) { return new NotFoundError('Resource not found'); } const bodyMessage = typeof context.response.data === 'object' && context.response.data !== null ? (context.response.data as { message?: string }).message : undefined; return new ApiError( bodyMessage ?? context.message, context.response.status, ); },});Rate Limit Errors
Section titled “Rate Limit Errors”When throwOnRateLimit is true (default), rate limit violations throw HttpClientError:
try { await client.get(url);} catch (error) { if (error instanceof HttpClientError) { // Could be a rate limit error or a server 429 console.log(error.message); }}Set throwOnRateLimit: false to wait instead of throwing:
const client = new HttpClient(stores, { throwOnRateLimit: false, maxWaitTime: 30_000, // Wait up to 30 seconds});Cancellation Errors
Section titled “Cancellation Errors”When a request is cancelled via AbortSignal, the error mimics a browser AbortError:
const controller = new AbortController();
try { const promise = client.get(url, { signal: controller.signal }); controller.abort(); await promise;} catch (error) { // error.name === 'AbortError' console.log('Request cancelled');}Dedupe Failure Behavior
Section titled “Dedupe Failure Behavior”When using deduplication, if the owner request fails, non-owner waiters receive undefined rather than a thrown error. This prevents cascading failures across deduplicated callers.