{"record":{"id":"f67425574d591298","repo":"BerriAI/litellm","slug":"apierror-exception-provider-error-str","errorCode":null,"errorMessage":"APIError: {exception_provider} - {error_str}","messagePattern":"APIError: (.+?) - (.+?)","errorType":"exception","errorClass":"APIError","httpStatus":null,"severity":"error","filePath":"litellm/litellm_core_utils/exception_mapping_utils.py","lineNumber":2145,"sourceCode":"            )\n        elif original_exception.status_code == 503:\n            raise ServiceUnavailableError(\n                message=f\"ServiceUnavailableError: {exception_provider} - {error_str}\",\n                model=model,\n                llm_provider=custom_llm_provider,\n                response=getattr(original_exception, \"response\", None),\n                litellm_debug_info=extra_information,\n            )\n        elif original_exception.status_code == 504:  # gateway timeout error\n            raise Timeout(\n                message=f\"Timeout Error: {exception_provider} - {error_str}\",\n                model=model,\n                llm_provider=custom_llm_provider,\n                litellm_debug_info=extra_information,\n                exception_status_code=original_exception.status_code,\n            )\n        else:\n            raise APIError(\n                status_code=original_exception.status_code,\n                message=f\"APIError: {exception_provider} - {error_str}\",\n                llm_provider=custom_llm_provider,\n                model=model,\n                request=getattr(original_exception, \"request\", None),\n                litellm_debug_info=extra_information,\n            )\n    else:\n        # if no status code then it is an APIConnectionError: https://github.com/openai/openai-python#handling-errors\n        raise APIConnectionError(\n            message=f\"APIConnectionError: {exception_provider} - {error_str}\",\n            llm_provider=custom_llm_provider,\n            model=model,\n            litellm_debug_info=extra_information,\n            request=httpx.Request(method=\"POST\", url=\"https://api.openai.com/v1/\"),\n        )\n\n","sourceCodeStart":2127,"sourceCodeEnd":2163,"githubUrl":"https://github.com/BerriAI/litellm/blob/77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8/litellm/litellm_core_utils/exception_mapping_utils.py#L2127-L2163","documentation":"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.","triggerScenarios":"Uncommon OpenRouter statuses such as 402 (payment/credit required), 403, 405, 410, or 500; any newly introduced status litellm doesn't specifically map yet.","commonSituations":"Out-of-credit accounts surfacing 402; new OpenRouter status codes after API changes; older litellm versions lacking newer mappings; upstream 500s from provider errors.","solutions":["Branch on e.status_code: 402 means billing/credits on the OpenRouter account; 5xx means retryable upstream trouble.","Upgrade litellm to pick up any newly added specific mappings.","For 402: add credits or switch keys; for 5xx: retry with backoff or failover to another provider.","Report unmapped recurring statuses with the response payload to the litellm repo."],"exampleFix":"# before\nlitellm.completion(model=\"openrouter/x\", messages=msgs)\n\n# after\ntry:\n    litellm.completion(model=\"openrouter/x\", messages=msgs)\nexcept litellm.APIError as e:\n    if e.status_code == 402:\n        raise RuntimeError(\"OpenRouter account out of credits\") from e\n    if e.status_code and e.status_code >= 500:\n        raise  # retryable upstream\n    raise","handlingStrategy":"try-catch","validationCode":null,"typeGuard":"def is_payment_error(e: Exception) -> bool:\n    return isinstance(e, litellm.APIError) and getattr(e, \"status_code\", None) == 402","tryCatchPattern":"try:\n    resp = litellm.completion(model=\"openrouter/...\", **kwargs)\nexcept litellm.APIError as e:\n    if getattr(e, \"status_code\", 0) >= 500:\n        retry_with_backoff()\n    else:\n        raise  # 402/403 etc. need human action, not retries","preventionTips":["Branch on status_code, not on message text, for unmapped OpenRouter errors.","Monitor for 402 specifically — it's the out-of-credit signal.","Keep litellm updated so unmapped codes shrink over time."],"tags":["openrouter","api-error","catch-all","status-code","litellm","exception-mapping"],"backgroundTag":"provider-api-error","analyzedSha":"77b7c6c40c0c5aa5fbcb1d6a1825ac39ca8829b8","analyzedAt":"2026-08-18T11:44:31.656Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}