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

# Error Handling

> Complete guide to API error responses and troubleshooting

## Overview

The Concentrate AI API uses standard HTTP status codes to indicate success or failure. All error responses include a JSON body with details about what went wrong.

## Error Response Format

All errors follow this structure:

```json theme={null}
{
  "error": "Error type or message",
  "message": "Detailed explanation (optional)",
  "model": "provider/model (for provider errors only)"
}
```

## Status Codes

| Status Code | Error Type            | Description                    |
| ----------- | --------------------- | ------------------------------ |
| `200`       | Success               | Request completed successfully |
| `400`       | Bad Request           | Invalid request parameters     |
| `401`       | Unauthorized          | Missing or invalid API key     |
| `402`       | Payment Required      | Insufficient credits           |
| `424`       | Failed Dependency     | Provider unavailable           |
| `429`       | Too Many Requests     | Rate limit exceeded            |
| `500`       | Internal Server Error | Server-side error              |

## Error Types

### 400 Bad Request

Invalid or malformed request parameters.

<AccordionGroup>
  <Accordion title="Invalid Model Name">
    ```json theme={null}
    {
      "error": "Bad Request",
      "message": "Invalid model name: 'invalid-model-xyz'"
    }
    ```

    **Causes:**

    * Model doesn't exist
    * Typo in model name
    * Unsupported model

    **Solution:**

    * Check [supported models list](/docs/api-reference/introduction#supported-models)
    * Verify spelling and format
    * Use provider prefix format: `provider/model`
  </Accordion>

  <Accordion title="Missing Required Fields">
    ```json theme={null}
    {
      "error": "Bad Request",
      "message": "Missing required field: 'input'"
    }
    ```

    **Causes:**

    * Required parameter not provided
    * Empty or null value

    **Solution:**

    * Include all required fields: `model` and `input`
    * Ensure values are not null or empty
  </Accordion>

  <Accordion title="Invalid Parameter Type">
    ```json theme={null}
    {
      "error": "Bad Request",
      "message": "Invalid type for 'temperature': expected number, got string"
    }
    ```

    **Causes:**

    * Wrong data type for parameter
    * Invalid enum value

    **Solution:**

    * Check parameter types in [API reference](/docs/api-reference/endpoint/create-response)
    * Use correct data types (string, number, boolean, etc.)
  </Accordion>

  <Accordion title="Invalid Parameter Value">
    ```json theme={null}
    {
      "error": "Bad Request",
      "message": "temperature must be between 0 and 2, got 3.5"
    }
    ```

    **Causes:**

    * Value outside allowed range
    * Negative value for positive-only fields

    **Solution:**

    * Review parameter constraints
    * `temperature`: 0.0 - 2.0
    * `top_p`: 0.0 - 1.0
    * `max_output_tokens`: > 0
  </Accordion>
</AccordionGroup>

### 401 Unauthorized

Authentication failed or API key is invalid.

```json theme={null}
{
  "error": "Unauthorized",
  "message": "Invalid API key"
}
```

**Causes:**

* API key is missing
* API key is invalid or revoked
* Wrong header format

**Solutions:**

<CodeGroup>
  ```bash Check Header Format theme={null}
  # Correct
  Authorization: Bearer sk-cn-v1-abc123xyz789

  # Incorrect
  Authorization: sk-cn-v1-abc123xyz789  # Missing "Bearer"
  Authorization: Bearer: sk-cn-v1-abc123xyz789  # Extra colon
  ```

  ```python Verify API Key theme={null}
  import requests

  # Test authentication
  response = requests.post(
      "https://api.concentrate.ai/v1/responses/health",
      headers={"Authorization": "Bearer YOUR_API_KEY"}
  )

  if response.status_code == 401:
      print("API key is invalid")
  else:
      print("API key is valid")
  ```
</CodeGroup>

<Warning>
  Get a new API key from the [Concentrate AI dashboard](https://concentrate.ai) if yours is invalid.
</Warning>

### 402 Payment Required

Insufficient credits to complete the request.

```json theme={null}
{
  "error": "Insufficient funds",
  "message": "Your account has insufficient credits. Please add credits to continue."
}
```

**Causes:**

* Account credit balance too low
* Request would exceed credit limit
* Free tier exhausted

**Solutions:**

1. **Check your balance:**
   * Visit [dashboard](https://concentrate.ai)
   * View credit usage and remaining balance

2. **Add credits:**
   * Purchase additional credits
   * Upgrade your plan

3. **Optimize requests:**
   * Reduce `max_output_tokens`
   * Use cost-optimized models
   * Enable auto routing with `routing: { strategy: "min", metric: "cost" }`

<CodeGroup>
  ```python Handle Insufficient Credits theme={null}
  import requests

  def make_request_with_budget(input_text):
      # Try with primary model
      response = requests.post(
          "https://api.concentrate.ai/v1/responses",
          headers={"Authorization": "Bearer YOUR_API_KEY"},
          json={
              "model": "gpt-5.2",
              "input": input_text,
              "max_output_tokens": 500
          }
      )

      if response.status_code == 402:
          # Try a cheaper model
          response = requests.post(
              "https://api.concentrate.ai/v1/responses",
              headers={"Authorization": "Bearer YOUR_API_KEY"},
              json={
                  "model": "auto",
                  "input": input_text,
                  "routing": {
                      "provider": {"sort": "cost"}
                  },
                  "max_output_tokens": 300
              }
          )

      return response.json()
  ```

  ```javascript Graceful Degradation theme={null}
  async function makeRequest(input) {
    try {
      const response = await fetch("https://api.concentrate.ai/v1/responses", {
        method: "POST",
        headers: {
          "Authorization": "Bearer YOUR_API_KEY",
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          model: "gpt-5.2",
          input
        })
      });

      if (response.status === 402) {
        // Notify user to add credits
        showCreditWarning();
        return null;
      }

      return await response.json();
    } catch (error) {
      handleError(error);
    }
  }
  ```
</CodeGroup>

### 424 Failed Dependency

The requested provider is unavailable.

```json theme={null}
{
  "error": "Model 'openai/gpt-5.2' Errored",
  "message": "Request to openai/gpt-5.2 failed because provider was unavailable",
  "model": "openai/gpt-5.2"
}
```

**Causes:**

* Provider experiencing outage
* Model temporarily unavailable
* Regional restrictions

**Solutions:**

1. **Retry with exponential backoff**
2. **Specify alternative provider**

<CodeGroup>
  ```python Retry with Backoff theme={null}
  import time
  import requests

  def request_with_retry(payload, max_retries=3):
      for attempt in range(max_retries):
          response = requests.post(
              "https://api.concentrate.ai/v1/responses",
              headers={"Authorization": "Bearer YOUR_API_KEY"},
              json=payload
          )

          if response.status_code == 424:
              if attempt < max_retries - 1:
                  # Exponential backoff: 1s, 2s, 4s
                  wait_time = 2 ** attempt
                  print(f"Provider error, retrying in {wait_time}s...")
                  time.sleep(wait_time)
                  continue

          return response.json()

      raise Exception("All retry attempts failed")
  ```

  ```javascript Try Alternative Provider theme={null}
  async function requestWithAlternative(input) {
    // Try specific provider
    let response = await fetch("https://api.concentrate.ai/v1/responses", {
      method: "POST",
      headers: {
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json"
      },
      body: JSON.stringify({
        model: "openai/gpt-5.2",
        input
      })
    });

    // If provider fails, try a different provider/model
    if (response.status === 424) {
      response = await fetch("https://api.concentrate.ai/v1/responses", {
        method: "POST",
        headers: {
          "Authorization": "Bearer YOUR_API_KEY",
          "Content-Type": "application/json"
        },
        body: JSON.stringify({
          model: "anthropic/claude-sonnet-4-5",
          input
        })
      });
    }

    return await response.json();
  }
  ```
</CodeGroup>

<Tip>
  Implement client-side retry logic or specify an alternative provider/model to handle provider unavailability.
</Tip>

### 429 Too Many Requests

Rate limit exceeded.

```json theme={null}
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Please retry after 60 seconds.",
  "retry_after": 60
}
```

**Causes:**

* Exceeded requests per minute limit
* Too many tokens per minute
* Burst limit exceeded

**Solutions:**

1. **Implement rate limiting in your code**
2. **Use exponential backoff**
3. **Batch requests when possible**
4. **Upgrade plan for higher limits**

<CodeGroup>
  ```python Rate Limit Handling theme={null}
  import time
  import requests

  def make_request_with_rate_limit(payload):
      while True:
          response = requests.post(
              "https://api.concentrate.ai/v1/responses",
              headers={"Authorization": "Bearer YOUR_API_KEY"},
              json=payload
          )

          if response.status_code == 429:
              # Get retry-after header
              retry_after = int(response.headers.get('Retry-After', 60))
              print(f"Rate limited. Waiting {retry_after}s...")
              time.sleep(retry_after)
              continue

          return response.json()
  ```

  ```javascript Token Bucket theme={null}
  class RateLimiter {
    constructor(tokensPerMinute) {
      this.tokens = tokensPerMinute;
      this.maxTokens = tokensPerMinute;
      this.lastRefill = Date.now();
    }

    async waitForToken() {
      // Refill tokens
      const now = Date.now();
      const timePassed = (now - this.lastRefill) / 1000;
      this.tokens = Math.min(
        this.maxTokens,
        this.tokens + (timePassed * this.maxTokens / 60)
      );
      this.lastRefill = now;

      // Wait if no tokens available
      if (this.tokens < 1) {
        const waitTime = ((1 - this.tokens) / (this.maxTokens / 60)) * 1000;
        await new Promise(resolve => setTimeout(resolve, waitTime));
        this.tokens = 1;
      }

      this.tokens -= 1;
    }

    async makeRequest(payload) {
      await this.waitForToken();

      return fetch("https://api.concentrate.ai/v1/responses", {
        method: "POST",
        headers: {
          "Authorization": "Bearer YOUR_API_KEY",
          "Content-Type": "application/json"
        },
        body: JSON.stringify(payload)
      });
    }
  }

  // Usage
  const limiter = new RateLimiter(60); // 60 requests per minute
  const response = await limiter.makeRequest({
    model: "gpt-5.2",
    input: "Hello"
  });
  ```
</CodeGroup>

### 500 Internal Server Error

Server-side error. These are rare and usually temporary.

```json theme={null}
{
  "error": "Internal server error",
  "message": "An unexpected error occurred. Please try again."
}
```

**Causes:**

* Temporary server issue
* Unexpected error condition
* Any provider internal error (e.g., Cloudflare server outage)

**Solutions:**

1. Retry the request after a short delay
2. If persists, contact support

## Best Practices

<AccordionGroup>
  <Accordion title="Implement comprehensive error handling" icon="shield">
    ```python theme={null}
    import requests
    from typing import Optional

    def make_safe_request(payload: dict) -> Optional[dict]:
        try:
            response = requests.post(
                "https://api.concentrate.ai/v1/responses",
                headers={"Authorization": "Bearer YOUR_API_KEY"},
                json=payload,
                timeout=30
            )

            # Handle different status codes
            if response.status_code == 200:
                return response.json()
            elif response.status_code == 400:
                print(f"Bad request: {response.json()['message']}")
            elif response.status_code == 401:
                print("Authentication failed - check API key")
            elif response.status_code == 402:
                print("Insufficient credits - please add funds")
            elif response.status_code == 424:
                print(f"Provider error: {response.json()['message']}")
                # Implement retry or try alternative provider
            elif response.status_code == 429:
                retry_after = int(response.headers.get('Retry-After', 60))
                print(f"Rate limited - retry after {retry_after}s")
            elif response.status_code == 500:
                print("Server error - will retry")

            return None

        except requests.exceptions.Timeout:
            print("Request timed out")
        except requests.exceptions.ConnectionError:
            print("Connection failed")
        except Exception as e:
            print(f"Unexpected error: {str(e)}")

        return None
    ```
  </Accordion>

  <Accordion title="Log errors for debugging" icon="file-lines">
    ```javascript theme={null}
    async function makeRequestWithLogging(payload) {
      const startTime = Date.now();

      try {
        const response = await fetch("https://api.concentrate.ai/v1/responses", {
          method: "POST",
          headers: {
            "Authorization": "Bearer YOUR_API_KEY",
            "Content-Type": "application/json"
          },
          body: JSON.stringify(payload)
        });

        const data = await response.json();
        const duration = Date.now() - startTime;

        // Log all requests
        console.log({
          timestamp: new Date().toISOString(),
          status: response.status,
          model: payload.model,
          duration,
          success: response.ok
        });

        if (!response.ok) {
          // Log error details
          console.error({
            error: data.error,
            message: data.message,
            payload
          });
        }

        return data;
      } catch (error) {
        console.error({
          timestamp: new Date().toISOString(),
          error: error.message,
          payload
        });
        throw error;
      }
    }
    ```
  </Accordion>

  <Accordion title="Use circuit breaker pattern" icon="bolt">
    ```python theme={null}
    from datetime import datetime, timedelta

    class CircuitBreaker:
        def __init__(self, failure_threshold=5, timeout=60):
            self.failure_threshold = failure_threshold
            self.timeout = timeout
            self.failures = 0
            self.last_failure_time = None
            self.state = "closed"  # closed, open, half-open

        def call(self, func, *args, **kwargs):
            if self.state == "open":
                if datetime.now() - self.last_failure_time > timedelta(seconds=self.timeout):
                    self.state = "half-open"
                else:
                    raise Exception("Circuit breaker is open")

            try:
                result = func(*args, **kwargs)
                self.on_success()
                return result
            except Exception as e:
                self.on_failure()
                raise

        def on_success(self):
            self.failures = 0
            self.state = "closed"

        def on_failure(self):
            self.failures += 1
            self.last_failure_time = datetime.now()
            if self.failures >= self.failure_threshold:
                self.state = "open"

    # Usage
    breaker = CircuitBreaker()

    try:
        response = breaker.call(make_api_request, payload)
    except Exception as e:
        print(f"Request failed: {e}")
    ```
  </Accordion>

  <Accordion title="Validate before sending" icon="check">
    ```typescript theme={null}
    interface RequestPayload {
      model: string;
      input: string | Message[];
      temperature?: number;
      max_output_tokens?: number;
    }

    function validatePayload(payload: RequestPayload): string[] {
      const errors: string[] = [];

      if (!payload.model) {
        errors.push("model is required");
      }

      if (!payload.input) {
        errors.push("input is required");
      }

      if (payload.temperature !== undefined) {
        if (payload.temperature < 0 || payload.temperature > 2) {
          errors.push("temperature must be between 0 and 2");
        }
      }

      if (payload.max_output_tokens !== undefined) {
        if (payload.max_output_tokens < 1) {
          errors.push("max_output_tokens must be positive");
        }
      }

      return errors;
    }

    // Usage
    const payload = { model: "gpt-5.2", input: "Hello" };
    const errors = validatePayload(payload);

    if (errors.length > 0) {
      console.error("Validation errors:", errors);
    } else {
      // Make request
    }
    ```
  </Accordion>
</AccordionGroup>

## Error Monitoring

Track and analyze errors in production:

<CodeGroup>
  ```python Error Metrics theme={null}
  from collections import Counter
  from datetime import datetime

  class ErrorTracker:
      def __init__(self):
          self.errors = []

      def log_error(self, status_code, error, message):
          self.errors.append({
              "timestamp": datetime.now(),
              "status_code": status_code,
              "error": error,
              "message": message
          })

      def get_error_summary(self):
          status_counts = Counter(e["status_code"] for e in self.errors)
          error_counts = Counter(e["error"] for e in self.errors)

          return {
              "total_errors": len(self.errors),
              "by_status": dict(status_counts),
              "by_type": dict(error_counts)
          }

  tracker = ErrorTracker()

  # Log errors
  if response.status_code != 200:
      data = response.json()
      tracker.log_error(
          response.status_code,
          data.get("error"),
          data.get("message")
      )

  # Get summary
  print(tracker.get_error_summary())
  ```

  ```javascript Error Analytics theme={null}
  class ErrorAnalytics {
    constructor() {
      this.errors = [];
    }

    logError(statusCode, error, message) {
      this.errors.push({
        timestamp: new Date(),
        statusCode,
        error,
        message
      });
    }

    getErrorRate(windowMinutes = 60) {
      const cutoff = new Date(Date.now() - windowMinutes * 60 * 1000);
      const recentErrors = this.errors.filter(e => e.timestamp > cutoff);
      return recentErrors.length;
    }

    getMostCommonError() {
      const counts = {};
      for (const error of this.errors) {
        counts[error.error] = (counts[error.error] || 0) + 1;
      }

      return Object.entries(counts)
        .sort((a, b) => b[1] - a[1])[0];
    }
  }
  ```
</CodeGroup>

## Debugging Checklist

When encountering errors, check:

* [ ] API key is valid and properly formatted
* [ ] Request payload matches schema requirements
* [ ] Parameter values are within allowed ranges
* [ ] Account has sufficient credits
* [ ] Model name is correct and supported
* [ ] Network connectivity is stable
* [ ] Timeout values are appropriate
* [ ] Error handling is implemented
* [ ] Retry logic is in place

## Related Documentation

<CardGroup cols={2}>
  <Card title="Create Response" icon="message" href="/docs/api-reference/endpoint/create-response">
    Main endpoint documentation
  </Card>

  <Card title="Auto Routing" icon="route" href="/docs/api-reference/endpoint/auto-routing">
    Automatic provider/model routing
  </Card>

  <Card title="Rate Limits" icon="gauge" href="/docs/api-reference/introduction#rate-limits">
    Understanding rate limits
  </Card>

  <Card title="Support" icon="life-ring" href="mailto:support@concentrate.ai">
    Contact support for help
  </Card>
</CardGroup>
