# How free-claude-code Maps Provider Errors to the Anthropic Error Format

> Learn how free-claude-code maps provider errors to the Anthropic error format using FastAPI exception handlers. It normalizes downstream LLM provider exceptions into a unified ProviderError hierarchy.

- Repository: [Ali Khokhar/free-claude-code](https://github.com/Alishahryar1/free-claude-code)
- Tags: how-to-guide
- Published: 2026-04-24

---

**free-claude-code normalizes downstream LLM provider exceptions into a unified `ProviderError` hierarchy and serializes them into Anthropic's canonical JSON error structure using FastAPI exception handlers.**

The open-source `free-claude-code` repository acts as a compatibility bridge between diverse LLM providers and Anthropic's API specification. When underlying services like OpenAI-compatible endpoints, NVIDIA NIM, or LM Studio return failures, the codebase translates these disparate error formats into a standardized Anthropic-compatible response. This article examines the specific mechanisms that map provider errors to the Anthropic error format.

## The Error Mapping Pipeline

The transformation from raw provider exceptions to Anthropic-compatible responses follows a strict sequence across three architectural layers.

### Step 1: Capturing Provider-Level Exceptions

Each provider client—such as [`providers/openai_compat.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/openai_compat.py) (line 289), [`providers/lmstudio/client.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/lmstudio/client.py), or [`providers/llamacpp/client.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/llamacpp/client.py)—wraps API requests in `try…except` blocks. When an HTTPX timeout, OpenAI error, or connection failure occurs, the client immediately invokes `map_error()` to initiate translation. This prevents provider-specific stack traces from leaking to the end user.

### Step 2: Generating User-Facing Messages

The `get_user_facing_error_message()` function in [`providers/common/error_mapping.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/common/error_mapping.py) (lines 17-53) inspects the raw exception to extract meaningful context. It handles:

- **HTTPX timeouts** and connection errors
- **OpenAI-specific error** objects with nested detail fields
- **HTTP status codes** from failed responses

The function returns a concise, non-empty string that avoids exposing internal implementation details while remaining actionable for developers.

### Step 3: Mapping to Concrete ProviderError Subclasses

The core `map_error()` function in [`providers/common/error_mapping.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/common/error_mapping.py) (lines 64-103) categorizes exceptions into typed errors within the `ProviderError` hierarchy:

- **AuthenticationError** for credential failures (HTTP 401)
- **RateLimitError** for throttling (HTTP 429)
- **InvalidRequestError** for malformed requests (HTTP 400)
- **OverloadedError** for provider capacity issues (HTTP 529)
- **APIError** as the generic fallback (HTTP 500)

This mapping also triggers the global rate-limit blocker when appropriate, preventing cascading requests to overwhelmed providers.

### Step 4: FastAPI Exception Handling

In [`api/app.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/api/app.py), the application registers dedicated exception handlers. The `provider_error_handler` (lines 8-15) catches `ProviderError` instances and returns `exc.to_anthropic_format()` as the response body, preserving the specific HTTP status code from the exception subclass. A fallback handler (lines 17-33) converts any uncaught exceptions into generic Anthropic `api_error` responses with HTTP 500.

## Anthropic-Compatible JSON Structure

Each `ProviderError` subclass implements `to_anthropic_format()` defined in [`providers/exceptions.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/exceptions.py). This method produces JSON matching Anthropic's specification exactly:

```json
{
  "type": "error",
  "error": {
    "type": "rate_limit_error",
    "message": "Provider rate limit reached. Please retry shortly."
  }
}

```

The mapping between internal exceptions and Anthropic error types follows this scheme:

| Subclass | Anthropic `error.type` | HTTP Status |
|----------|------------------------|-------------|
| `AuthenticationError` | `authentication_error` | 401 |
| `InvalidRequestError` | `invalid_request_error` | 400 |
| `RateLimitError` | `rate_limit_error` | 429 |
| `OverloadedError` | `overloaded_error` | 529 |
| `APIError` | `api_error` | 500 |

## Practical Example: Mapping a Rate Limit

When an underlying provider returns HTTP 429, the flow executes as follows:

```python
from providers.common import map_error
import httpx

try:
    response = httpx.get("https://example.com")
    response.raise_for_status()
except httpx.HTTPStatusError as e:
    # e.response.status_code == 429

    mapped = map_error(e)  # Returns RateLimitError

    raise mapped

```

The resulting `RateLimitError` carries the message "Provider rate limit reached. Please retry shortly." When the FastAPI handler in [`api/app.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/api/app.py) processes this exception, it returns HTTP 429 with the Anthropic-formatted JSON body shown above.

## Summary

- Provider clients in files like [`providers/openai_compat.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/openai_compat.py) and [`providers/lmstudio/client.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/lmstudio/client.py) wrap requests to catch native exceptions before they propagate.
- `map_error()` in [`providers/common/error_mapping.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/common/error_mapping.py) (lines 64-103) translates raw exceptions into typed `ProviderError` subclasses with appropriate HTTP status codes.
- The `to_anthropic_format()` method in [`providers/exceptions.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/exceptions.py) serializes errors into Anthropic's canonical JSON structure with `type: "error"` wrapping.
- FastAPI exception handlers in [`api/app.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/api/app.py) ensure all responses conform to the Anthropic specification regardless of which upstream provider generated the failure.

## Frequently Asked Questions

### What happens when a provider returns an unrecognized error type?

Unrecognized exceptions default to the base `APIError` class, which generates an Anthropic `api_error` type with HTTP status 500. The handler in [`api/app.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/api/app.py) (lines 17-33) serves as the ultimate fallback for any exception not matching the `ProviderError` hierarchy, ensuring the client always receives valid JSON.

### How does free-claude-code handle rate limiting specifically?

When `map_error()` in [`providers/common/error_mapping.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/common/error_mapping.py) detects HTTP 429 or provider-specific rate limit signals, it returns a `RateLimitError` instance. This triggers HTTP status 429 in the response and includes the error type `rate_limit_error` in the JSON body. The system also activates the global rate-limit blocker to prevent cascading requests to the overwhelmed provider.

### Can request IDs be included in error responses?

Yes. The `append_request_id()` function in [`providers/common/error_mapping.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/common/error_mapping.py) (lines 56-62) allows callers to embed provider-specific request identifiers into error messages using the syntax `f"{message} (Request ID: {request_id})"`. This aids debugging while maintaining the Anthropic-compatible JSON structure, as the message field accepts arbitrary strings.

### Which file defines the Anthropic error format conversion?

The `to_anthropic_format()` method is implemented in [`providers/exceptions.py`](https://github.com/Alishahryar1/free-claude-code/blob/main/providers/exceptions.py). This file defines the `ProviderError` base class and its subclasses (`AuthenticationError`, `RateLimitError`, `InvalidRequestError`, `OverloadedError`, and `APIError`), each specifying the exact `error.type` string and HTTP status code required by the Anthropic API specification.