BerriAI/litellm · error · APIError

APIError

Error message

APIError: {exception_provider} - {error_str}

What it means

Catch-all of _map_openrouter_exception: any OpenRouter status not in {400,401,404,408,422,429,503,504} becomes litellm.APIError, preserving status_code, the request (when present), model, and debug info. The message 'APIError: <provider> - <error_str>' still carries OpenRouter's raw error text.

Solutions

  1. Branch on e.status_code: 402 means billing/credits on the OpenRouter account; 5xx means retryable upstream trouble.
  2. Upgrade litellm to pick up any newly added specific mappings.
  3. For 402: add credits or switch keys; for 5xx: retry with backoff or failover to another provider.
  4. Report unmapped recurring statuses with the response payload to the litellm repo.

Example fix

# before
litellm.completion(model="openrouter/x", messages=msgs)

# after
try:
    litellm.completion(model="openrouter/x", messages=msgs)
except litellm.APIError as e:
    if e.status_code == 402:
        raise RuntimeError("OpenRouter account out of credits") from e
    if e.status_code and e.status_code >= 500:
        raise  # retryable upstream
    raise
Defensive patterns

Strategy: try-catch

Type guard

def is_payment_error(e: Exception) -> bool:
    return isinstance(e, litellm.APIError) and getattr(e, "status_code", None) == 402

Try / catch

try:
    resp = litellm.completion(model="openrouter/...", **kwargs)
except litellm.APIError as e:
    if getattr(e, "status_code", 0) >= 500:
        retry_with_backoff()
    else:
        raise  # 402/403 etc. need human action, not retries

Prevention

When it happens

Trigger: Uncommon OpenRouter statuses such as 402 (payment/credit required), 403, 405, 410, or 500; any newly introduced status litellm doesn't specifically map yet.

Common situations: Out-of-credit accounts surfacing 402; new OpenRouter status codes after API changes; older litellm versions lacking newer mappings; upstream 500s from provider errors.

Related errors


AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18). Data as JSON: /api/errors/f67425574d591298. Report an issue: GitHub.

Appendix: source

Thrown at litellm/litellm_core_utils/exception_mapping_utils.py:2145

            )
        elif original_exception.status_code == 503:
            raise ServiceUnavailableError(
                message=f"ServiceUnavailableError: {exception_provider} - {error_str}",
                model=model,
                llm_provider=custom_llm_provider,
                response=getattr(original_exception, "response", None),
                litellm_debug_info=extra_information,
            )
        elif original_exception.status_code == 504:  # gateway timeout error
            raise Timeout(
                message=f"Timeout Error: {exception_provider} - {error_str}",
                model=model,
                llm_provider=custom_llm_provider,
                litellm_debug_info=extra_information,
                exception_status_code=original_exception.status_code,
            )
        else:
            raise APIError(
                status_code=original_exception.status_code,
                message=f"APIError: {exception_provider} - {error_str}",
                llm_provider=custom_llm_provider,
                model=model,
                request=getattr(original_exception, "request", None),
                litellm_debug_info=extra_information,
            )
    else:
        # if no status code then it is an APIConnectionError: https://github.com/openai/openai-python#handling-errors
        raise APIConnectionError(
            message=f"APIConnectionError: {exception_provider} - {error_str}",
            llm_provider=custom_llm_provider,
            model=model,
            litellm_debug_info=extra_information,
            request=httpx.Request(method="POST", url="https://api.openai.com/v1/"),
        )

View on GitHub (pinned to 77b7c6c40c)