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

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 (line 289), providers/lmstudio/client.py, or 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 (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 (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, 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. This method produces JSON matching Anthropic's specification exactly:

{
  "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:

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 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 and providers/lmstudio/client.py wrap requests to catch native exceptions before they propagate.
  • map_error() in 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 serializes errors into Anthropic's canonical JSON structure with type: "error" wrapping.
  • FastAPI exception handlers in 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 (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 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 (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. 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.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →