Skip to Content
GuidesError Handling

Last Updated: 1/27/2026


Error Handling

Handle API errors gracefully in your application.

Error Types

import { ApiError, NetworkError, ValidationError, RateLimitError, AuthenticationError, } from '@example/sdk';
Error TypeCauseRecovery
ApiErrorAPI returned an errorCheck error code
NetworkErrorConnection failedRetry with backoff
ValidationErrorInvalid inputFix input data
RateLimitErrorToo many requestsWait and retry
AuthenticationErrorInvalid credentialsCheck API key

:::info All errors extend the base ApiError class with additional context. :::

Basic Error Handling

import { createClient, ApiError } from '@example/sdk'; const client = createClient({ apiKey: process.env.API_KEY! }); try { const user = await client.users.get('user_123'); console.log(user); } catch (error) { if (error instanceof ApiError) { console.error(`Error ${error.code}: ${error.message}`); } else { throw error; // Re-throw unexpected errors } }

Specific Error Handling

import { ApiError, ValidationError, RateLimitError, AuthenticationError, NotFoundError, } from '@example/sdk'; async function getUser(id: string) { try { return await client.users.get(id); } catch (error) { if (error instanceof NotFoundError) { console.log(`User ${id} not found`); return null; } if (error instanceof ValidationError) { console.error('Invalid input:', error.issues); // [{ field: 'id', message: 'Must be a valid UUID' }] throw error; } if (error instanceof RateLimitError) { console.log(`Rate limited. Retry after ${error.retryAfter}ms`); await sleep(error.retryAfter); return getUser(id); // Retry } if (error instanceof AuthenticationError) { console.error('Invalid API key'); throw error; } throw error; } }

:::warning Always handle RateLimitError with exponential backoff to avoid being blocked. :::

Error Properties

try { await client.users.create({ email: 'invalid' }); } catch (error) { if (error instanceof ApiError) { console.log('Code:', error.code); // 'VALIDATION_ERROR' console.log('Message:', error.message); // 'Invalid email format' console.log('Status:', error.status); // 400 console.log('Request ID:', error.requestId); // 'req_abc123' // For validation errors if (error instanceof ValidationError) { console.log('Issues:', error.issues); // [{ field: 'email', message: 'Invalid email format' }] } } }

:::tip Include the requestId when contacting support for faster debugging. :::

Retry Logic

import { createClient, RateLimitError, NetworkError } from '@example/sdk'; async function withRetry<T>( fn: () => Promise<T>, maxRetries = 3, ): Promise<T> { let lastError: Error | undefined; for (let attempt = 1; attempt <= maxRetries; attempt++) { try { return await fn(); } catch (error) { lastError = error as Error; // Don't retry validation or auth errors if (error instanceof ValidationError) throw error; if (error instanceof AuthenticationError) throw error; // Retry rate limits and network errors if (error instanceof RateLimitError) { await sleep(error.retryAfter); continue; } if (error instanceof NetworkError) { const backoff = Math.pow(2, attempt) * 1000; console.log(`Retry ${attempt}/${maxRetries} in ${backoff}ms`); await sleep(backoff); continue; } throw error; } } throw lastError; } // Usage const user = await withRetry(() => client.users.get('user_123'));

:::danger Set a maximum retry limit to prevent infinite loops. 3-5 retries is typically sufficient. :::

Global Error Handler

const client = createClient({ apiKey: process.env.API_KEY!, onError: (error) => { // Log all errors to monitoring service logger.error('API Error', { code: error.code, message: error.message, requestId: error.requestId, }); // Send to error tracking Sentry.captureException(error); }, });

:::note The onError hook is called for all errors, even those you catch locally. :::