Error Handling

Learn how to handle errors and exceptions when using our API.

Error Structure

Our API returns standardized error responses to help you identify and resolve issues quickly. All errors follow this structure:

{
  "error": {
    "code": "resource_not_found",
    "message": "The requested resource was not found",
    "details": {
      "resource": "item",
      "id": "non-existent-id"
    },
    "requestId": "req_1234567890"
  }
}
json

The error object contains the following fields:

FieldDescription
codeA machine-readable error code that identifies the type of error
messageA human-readable description of the error
detailsAdditional context about the error (varies by error type)
requestIdA unique identifier for the request, useful for troubleshooting with support

Common Error Codes

Here are the most common error codes you might encounter:

Error CodeHTTP StatusDescription
authentication_required401No valid authentication credentials were provided
invalid_api_key401The API key provided is invalid or has been revoked
permission_denied403The authenticated user doesn't have permission to perform the requested action
resource_not_found404The requested resource doesn't exist
validation_error422The request data failed validation
rate_limit_exceeded429You've exceeded the rate limit for API requests
internal_error500An unexpected error occurred on our servers
service_unavailable503The service is temporarily unavailable, usually due to maintenance

Handling Errors in Code

Our SDK provides built-in error handling mechanisms. Here's how to handle errors in your code:

import { Client, ApiError } from '@acme/sdk';

const client = new Client({
  apiKey: 'YOUR_API_KEY',
});

// Basic error handling with try/catch
async function handleBasicErrors() {
  try {
    // This will fail if the item doesn't exist
    const item = await client.items.get('non-existent-id');
    return item;
  } catch (error) {
    if (error instanceof ApiError) {
      console.error('API Error:', error.code, error.message);
      console.error('Request ID:', error.requestId);
      
      // Handle specific error types
      if (error.code === 'resource_not_found') {
        console.log('The requested item does not exist');
      } else if (error.code === 'permission_denied') {
        console.log('You do not have permission to access this item');
      }
    } else {
      // Handle non-API errors (network issues, etc.)
      console.error('Unexpected error:', error);
    }
    
    // Return a fallback or re-throw the error
    return null;
  }
}

// Handling validation errors
async function handleValidationErrors() {
  try {
    const newItem = await client.items.create({
      // Missing required fields or invalid data
    });
    return newItem;
  } catch (error) {
    if (error instanceof ApiError && error.code === 'validation_error') {
      console.error('Validation Error:', error.message);
      
      // The details field contains validation errors for specific fields
      if (error.details && error.details.fields) {
        for (const [field, fieldErrors] of Object.entries(error.details.fields)) {
          console.error(`Field "${field}" has errors: ${fieldErrors.join(', ')}`);
        }
      }
    } else {
      console.error('Unexpected error:', error);
    }
    
    return null;
  }
}
javascript

Retry Strategies

Some errors are transient and can be resolved by retrying the request. Here's how to implement retry logic:

import { Client, ApiError } from '@acme/sdk';

const client = new Client({
  apiKey: 'YOUR_API_KEY',
});

// Simple retry function with exponential backoff
async function withRetry(fn, maxRetries = 3, initialDelay = 1000) {
  let retries = 0;
  
  while (true) {
    try {
      return await fn();
    } catch (error) {
      // Don't retry if we've reached the maximum retries
      if (retries >= maxRetries) {
        throw error;
      }
      
      // Only retry for specific error types
      if (error instanceof ApiError) {
        const statusCode = error.statusCode;
        
        // Don't retry client errors (except rate limiting)
        if (statusCode >= 400 && statusCode < 500 && statusCode !== 429) {
          throw error;
        }
      }
      
      // Increment retry counter
      retries++;
      
      // Calculate delay with exponential backoff and jitter
      const delay = initialDelay * Math.pow(2, retries - 1) * (0.5 + Math.random() * 0.5);
      
      console.log(`Retrying after ${delay}ms (attempt ${retries} of ${maxRetries})`);
      
      // Wait before retrying
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

// Example usage
async function fetchWithRetry() {
  return withRetry(() => client.items.list());
}

// Example with rate limiting
async function handleRateLimiting() {
  try {
    const result = await withRetry(() => client.items.list(), 5, 2000);
    return result;
  } catch (error) {
    if (error instanceof ApiError && error.code === 'rate_limit_exceeded') {
      console.error('Rate limit exceeded even after retries');
      
      // Get rate limit information from the error details
      if (error.details && error.details.rateLimit) {
        const { limit, remaining, reset } = error.details.rateLimit;
        const resetDate = new Date(reset * 1000);
        
        console.log(`Rate limit: ${limit}, Remaining: ${remaining}, Resets at: ${resetDate}`);
      }
    }
    
    throw error;
  }
}
javascript

Debugging Tips

When troubleshooting API errors, consider these tips:

Enable Verbose Logging

Our SDK supports detailed logging to help with debugging:

import { Client } from '@acme/sdk';

const client = new Client({
  apiKey: 'YOUR_API_KEY',
  debug: true, // Enable debug mode
});

// You can also configure a custom logger
const clientWithCustomLogger = new Client({
  apiKey: 'YOUR_API_KEY',
  logger: {
    debug: (message) => console.debug(`[ACME SDK] ${message}`),
    info: (message) => console.info(`[ACME SDK] ${message}`),
    warn: (message) => console.warn(`[ACME SDK] ${message}`),
    error: (message) => console.error(`[ACME SDK] ${message}`),
  },
});
javascript

Check Request IDs

Every API response includes a unique request ID in both successful responses and errors. Always include this ID when contacting support about an issue.

Use the API Dashboard

Our API dashboard provides logs of recent requests, which can help identify issues. You can access it at dashboard.example.com/api-logs.

Was this page helpful?
Last updated on 3/19/2025