> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stateset.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Error Handling

> Comprehensive guide to API error responses and handling strategies

<Info>
  StateSet API uses standard HTTP response codes and provides detailed error information to help you handle issues gracefully.
</Info>

## Error Response Format

All errors follow a consistent JSON structure to make error handling predictable:

```json theme={null}
{
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "type": "error_type",
    "details": {
      // Additional context-specific information
    },
    "request_id": "req_1NXWPnCo6bFb1KQto6C8OWvE",
    "timestamp": "2024-01-15T10:30:00Z",
    "documentation_url": "https://docs.stateset.com/errors/ERROR_CODE"
  }
}
```

## HTTP Status Codes

| Status Code | Meaning               | Common Causes                                  |
| ----------- | --------------------- | ---------------------------------------------- |
| **200**     | OK                    | Request succeeded                              |
| **201**     | Created               | Resource successfully created                  |
| **202**     | Accepted              | Request accepted for async processing          |
| **204**     | No Content            | Request succeeded with no response body        |
| **400**     | Bad Request           | Invalid request parameters or malformed syntax |
| **401**     | Unauthorized          | Missing or invalid authentication              |
| **403**     | Forbidden             | Valid auth but insufficient permissions        |
| **404**     | Not Found             | Resource doesn't exist                         |
| **409**     | Conflict              | Resource conflict or duplicate                 |
| **422**     | Unprocessable Entity  | Valid syntax but semantic errors               |
| **429**     | Too Many Requests     | Rate limit exceeded                            |
| **500**     | Internal Server Error | Server error - retry with backoff              |
| **502**     | Bad Gateway           | Upstream service error                         |
| **503**     | Service Unavailable   | Temporary service outage                       |

## Error Types and Codes

### Authentication Errors (401)

| Error Code             | Description                      | Resolution                 |
| ---------------------- | -------------------------------- | -------------------------- |
| `INVALID_API_KEY`      | API key is invalid or revoked    | Check key in dashboard     |
| `EXPIRED_API_KEY`      | API key has expired              | Generate new API key       |
| `MISSING_AUTH_HEADER`  | No Authorization header provided | Include Bearer token       |
| `INVALID_TOKEN_FORMAT` | Token format is incorrect        | Use `Bearer sk_...` format |
| `INACTIVE_ACCOUNT`     | Account is suspended or inactive | Contact support            |

### Authorization Errors (403)

| Error Code                 | Description                           | Resolution                 |
| -------------------------- | ------------------------------------- | -------------------------- |
| `INSUFFICIENT_PERMISSIONS` | API key lacks required permissions    | Use key with proper scopes |
| `RESOURCE_ACCESS_DENIED`   | Cannot access this specific resource  | Check resource ownership   |
| `PLAN_LIMIT_EXCEEDED`      | Feature not available on current plan | Upgrade plan               |
| `IP_NOT_ALLOWED`           | Request from unauthorized IP          | Add IP to allowlist        |

### Validation Errors (400/422)

| Error Code               | Description                           | Resolution                  |
| ------------------------ | ------------------------------------- | --------------------------- |
| `VALIDATION_ERROR`       | Request validation failed             | Check field requirements    |
| `MISSING_REQUIRED_FIELD` | Required field not provided           | Include all required fields |
| `INVALID_FIELD_VALUE`    | Field value doesn't meet requirements | Validate field format       |
| `INVALID_ENUM_VALUE`     | Value not in allowed enum list        | Use accepted values         |
| `FIELD_TOO_LONG`         | Field exceeds maximum length          | Truncate field value        |
| `INVALID_DATE_FORMAT`    | Date format incorrect                 | Use ISO 8601 format         |

### Resource Errors (404/409)

| Error Code                | Description                         | Resolution                          |
| ------------------------- | ----------------------------------- | ----------------------------------- |
| `RESOURCE_NOT_FOUND`      | Requested resource doesn't exist    | Verify resource ID                  |
| `RESOURCE_ALREADY_EXISTS` | Duplicate resource creation attempt | Use existing resource               |
| `RESOURCE_LOCKED`         | Resource is locked for editing      | Wait and retry                      |
| `RESOURCE_ARCHIVED`       | Resource has been archived          | Unarchive or use different resource |
| `PARENT_NOT_FOUND`        | Parent resource doesn't exist       | Create parent first                 |

### Business Logic Errors (422)

| Error Code                 | Description                    | Resolution                     |
| -------------------------- | ------------------------------ | ------------------------------ |
| `INSUFFICIENT_INVENTORY`   | Not enough inventory available | Reduce quantity or check stock |
| `PAYMENT_FAILED`           | Payment processing failed      | Verify payment details         |
| `INVALID_STATE_TRANSITION` | Invalid status change          | Check allowed transitions      |
| `OUTSIDE_RETURN_WINDOW`    | Return period expired          | Check return policy            |
| `DUPLICATE_REQUEST`        | Duplicate request detected     | Use idempotency key            |

### Rate Limiting Errors (429)

```json theme={null}
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded",
    "type": "rate_limit_error",
    "details": {
      "limit": 100,
      "remaining": 0,
      "reset_at": "2024-01-15T10:35:00Z",
      "retry_after": 300
    }
  }
}
```

## Error Handling Best Practices

### 1. Implement Exponential Backoff

<CodeGroup>
  ```javascript Node.js theme={null}
  class APIClient {
    async requestWithRetry(url, options, maxRetries = 3) {
      let lastError;
      
      for (let attempt = 0; attempt <= maxRetries; attempt++) {
        try {
          const response = await fetch(url, options);
          
          if (response.status === 429) {
            const retryAfter = response.headers.get('X-RateLimit-Retry-After');
            const delay = retryAfter 
              ? parseInt(retryAfter) * 1000 
              : Math.min(1000 * Math.pow(2, attempt), 32000);
            
            if (attempt < maxRetries) {
              await new Promise(resolve => setTimeout(resolve, delay));
              continue;
            }
          }
          
          if (!response.ok) {
            const error = await response.json();
            throw new APIError(error);
          }
          
          return response.json();
        } catch (error) {
          lastError = error;
          
          if (attempt < maxRetries && this.isRetryable(error)) {
            const delay = Math.min(1000 * Math.pow(2, attempt), 32000);
            await new Promise(resolve => setTimeout(resolve, delay));
            continue;
          }
          
          throw error;
        }
      }
      
      throw lastError;
    }
    
    isRetryable(error) {
      const retryableCodes = [429, 500, 502, 503, 504];
      return error.status && retryableCodes.includes(error.status);
    }
  }
  ```

  ```python Python theme={null}
  import time
  import requests
  from typing import Optional, Dict, Any

  class APIClient:
      def __init__(self, api_key: str):
          self.api_key = api_key
          self.base_url = "https://api.stateset.com/v1"
          
      def request_with_retry(
          self,
          method: str,
          endpoint: str,
          data: Optional[Dict] = None,
          max_retries: int = 3
      ) -> Dict[str, Any]:
          url = f"{self.base_url}{endpoint}"
          headers = {
              "Authorization": f"Bearer {self.api_key}",
              "Content-Type": "application/json"
          }
          
          last_exception = None
          
          for attempt in range(max_retries + 1):
              try:
                  response = requests.request(
                      method,
                      url,
                      json=data,
                      headers=headers
                  )
                  
                  if response.status_code == 429:
                      retry_after = response.headers.get('X-RateLimit-Retry-After', 1)
                      delay = min(
                          int(retry_after),
                          2 ** attempt
                      )
                      
                      if attempt < max_retries:
                          time.sleep(delay)
                          continue
                  
                  response.raise_for_status()
                  return response.json()
                  
              except requests.exceptions.RequestException as e:
                  last_exception = e
                  
                  if attempt < max_retries and self._is_retryable(e):
                      delay = min(2 ** attempt, 32)
                      time.sleep(delay)
                      continue
                      
                  raise
          
          raise last_exception
      
      def _is_retryable(self, error: Exception) -> bool:
          if hasattr(error, 'response'):
              retryable_codes = {429, 500, 502, 503, 504}
              return error.response.status_code in retryable_codes
          return False
  ```
</CodeGroup>

### 2. Handle Specific Error Types

```javascript theme={null}
class ErrorHandler {
  handle(error) {
    switch (error.code) {
      case 'INVALID_API_KEY':
        // Refresh API key or prompt for new one
        return this.refreshApiKey();
        
      case 'INSUFFICIENT_PERMISSIONS':
        // Inform user about permission requirements
        return this.showPermissionError(error.details);
        
      case 'VALIDATION_ERROR':
        // Show field-specific errors
        return this.showValidationErrors(error.details);
        
      case 'RATE_LIMITED':
        // Implement backoff and queue
        return this.queueRequest(error.details.retry_after);
        
      case 'INSUFFICIENT_INVENTORY':
        // Update UI with available quantity
        return this.updateInventory(error.details);
        
      default:
        // Generic error handling
        return this.showGenericError(error.message);
    }
  }
}
```

### 3. Implement Circuit Breaker Pattern

```javascript theme={null}
class CircuitBreaker {
  constructor(threshold = 5, timeout = 60000) {
    this.failureCount = 0;
    this.failureThreshold = threshold;
    this.timeout = timeout;
    this.state = 'CLOSED';
    this.nextAttempt = Date.now();
  }
  
  async call(fn) {
    if (this.state === 'OPEN') {
      if (Date.now() < this.nextAttempt) {
        throw new Error('Circuit breaker is OPEN');
      }
      this.state = 'HALF_OPEN';
    }
    
    try {
      const result = await fn();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }
  
  onSuccess() {
    this.failureCount = 0;
    this.state = 'CLOSED';
  }
  
  onFailure() {
    this.failureCount++;
    if (this.failureCount >= this.failureThreshold) {
      this.state = 'OPEN';
      this.nextAttempt = Date.now() + this.timeout;
    }
  }
}
```

### 4. Log and Monitor Errors

```javascript theme={null}
class ErrorLogger {
  log(error, context) {
    const errorData = {
      timestamp: new Date().toISOString(),
      request_id: error.request_id,
      error_code: error.code,
      message: error.message,
      context: {
        user_id: context.userId,
        endpoint: context.endpoint,
        method: context.method,
        ...context
      },
      stack_trace: error.stack
    };
    
    // Send to logging service
    logger.error(errorData);
    
    // Track in analytics
    analytics.track('API_ERROR', errorData);
    
    // Alert on critical errors
    if (this.isCritical(error)) {
      alerting.notify(errorData);
    }
  }
  
  isCritical(error) {
    const criticalCodes = [
      'PAYMENT_FAILED',
      'SERVICE_UNAVAILABLE',
      'DATABASE_ERROR'
    ];
    return criticalCodes.includes(error.code);
  }
}
```

## Error Recovery Strategies

### Idempotency for Safe Retries

```javascript theme={null}
// Use idempotency keys to safely retry requests
const createOrder = async (orderData) => {
  const idempotencyKey = `order-${uuidv4()}`;
  
  try {
    return await api.post('/orders', orderData, {
      headers: {
        'Idempotency-Key': idempotencyKey
      }
    });
  } catch (error) {
    if (error.code === 'DUPLICATE_REQUEST') {
      // Return existing order from previous request
      return error.details.existing_resource;
    }
    throw error;
  }
};
```

### Graceful Degradation

```javascript theme={null}
class ResilientClient {
  async getProductWithFallback(productId) {
    try {
      // Try primary API
      return await this.api.get(`/products/${productId}`);
    } catch (error) {
      if (error.code === 'SERVICE_UNAVAILABLE') {
        // Fall back to cache
        const cached = await this.cache.get(`product:${productId}`);
        if (cached) {
          return { ...cached, from_cache: true };
        }
        
        // Fall back to secondary service
        return await this.secondaryApi.get(`/products/${productId}`);
      }
      throw error;
    }
  }
}
```

## Common Error Scenarios

### Handling Validation Errors

```json theme={null}
// Request
POST /v1/orders
{
  "customer_email": "invalid-email",
  "items": []
}

// Response (422)
{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "Request validation failed",
    "type": "validation_error",
    "details": {
      "errors": [
        {
          "field": "customer_email",
          "message": "Invalid email format",
          "expected": "valid email address"
        },
        {
          "field": "items",
          "message": "At least one item is required",
          "expected": "non-empty array"
        }
      ]
    },
    "request_id": "req_abc123"
  }
}
```

### Handling Resource Conflicts

```json theme={null}
// Request
POST /v1/customers
{
  "email": "existing@example.com"
}

// Response (409)
{
  "error": {
    "code": "RESOURCE_ALREADY_EXISTS",
    "message": "Customer with this email already exists",
    "type": "conflict_error",
    "details": {
      "existing_id": "cus_123abc",
      "field": "email",
      "value": "existing@example.com"
    },
    "request_id": "req_def456"
  }
}
```

## Error Webhooks

Configure error webhooks to receive notifications for critical failures:

```json theme={null}
{
  "event": "api.error",
  "created": "2024-01-15T10:30:00Z",
  "data": {
    "error_code": "PAYMENT_FAILED",
    "request_id": "req_xyz789",
    "customer_id": "cus_123",
    "order_id": "ord_456",
    "amount": 9999,
    "currency": "usd"
  }
}
```

## SDK Error Handling

Our SDKs provide built-in error handling:

<CodeGroup>
  ```javascript Node.js SDK theme={null}
  try {
    const order = await stateset.orders.create({
      customer_email: 'customer@example.com',
      items: [...]
    });
  } catch (error) {
    if (error.code === 'INSUFFICIENT_INVENTORY') {
      // Handle inventory shortage
      const available = error.details.available_items;
      console.log(`Only ${available} items available`);
    } else if (error.code === 'VALIDATION_ERROR') {
      // Handle validation errors
      error.details.errors.forEach(err => {
        console.log(`${err.field}: ${err.message}`);
      });
    } else {
      // Generic error handling
      console.error('Unexpected error:', error.message);
    }
  }
  ```

  ```python Python SDK theme={null}
  from stateset import StatesetError, ValidationError, RateLimitError

  try:
      order = stateset.orders.create(
          customer_email='customer@example.com',
          items=[...]
      )
  except ValidationError as e:
      # Handle validation errors
      for error in e.errors:
          print(f"{error['field']}: {error['message']}")
  except RateLimitError as e:
      # Handle rate limiting
      print(f"Rate limited. Retry after {e.retry_after} seconds")
  except StatesetError as e:
      # Handle other API errors
      print(f"API error: {e.code} - {e.message}")
  ```
</CodeGroup>

## Testing Error Scenarios

Use test mode to simulate error conditions:

```bash theme={null}
# Trigger specific error in test mode
curl -X POST https://api.sandbox.stateset.com/v1/orders \
  -H "Authorization: Bearer sk_test_..." \
  -H "X-Test-Error-Code: INSUFFICIENT_INVENTORY" \
  -d '{...}'
```

## Support

If you encounter persistent errors or need help with error handling:

* **API Status**: Check [status.stateset.com](https://status.stateset.com)
* **Support**: Contact [api-support@stateset.com](mailto:api-support@stateset.com)
* **Discord**: Join our [developer community](https://discord.gg/VfcaqgZywq)

***

**Related:** [Rate Limiting](/api-reference/rate-limiting) | [Authentication](/api-reference/authentication) | [Webhooks](/api-reference/webhooks)
