BerriAI/litellm · error · OpenAIError

error_text

Error message

error_text

What it means

The text-completion completion() wraps everything in try/except and converts any exception into an OpenAIError: status from e.status_code (default 500), headers from e.headers or e.response.headers, message from e.text if present else str(e). So this error is the normalized re-raise of any downstream failure — HTTP errors from the server, timeouts, or the 422 missing-params error above.

Source

Thrown at litellm/llms/openai/completion/handler.py:163

                logging_obj.post_call(
                    api_key=api_key,
                    original_response=response_json,
                    additional_args={
                        "headers": headers,
                        "api_base": api_base,
                    },
                )

                ## RESPONSE OBJECT
                return TextCompletionResponse(**response_json)
        except Exception as e:
            status_code: Final = getattr(e, "status_code", 500)
            error_headers = getattr(e, "headers", None)
            error_text: Final = getattr(e, "text", str(e))
            error_response: Final = getattr(e, "response", None)
            if error_headers is None and error_response:
                error_headers = getattr(error_response, "headers", None)
            raise OpenAIError(status_code=status_code, message=error_text, headers=error_headers)

    async def acompletion(
        self,
        logging_obj,
        api_base: str,
        data: dict,
        headers: dict,
        model_response: ModelResponse,
        api_key: str,
        model: str,
        timeout: float,
        max_retries: int,
        organization: str | None = None,
        client=None,
    ):
        try:
            if client is None:
                openai_aclient = AsyncOpenAI(

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Read the message: if it contains JSON error body text, that is the upstream server's error — act on it (auth, quota, params).
  2. If the message is an exception string (e.g. 'Connection refused.'), fix network/api_base issues.
  3. Catch OpenAIError and inspect .status_code and .headers to branch on auth (401) vs rate limit (429) vs server (5xx).
  4. Reproduce with curl against the same api_base/key to confirm the upstream behavior.
Defensive patterns

Strategy: try-catch

Try / catch

try:
    resp = litellm.text_completion(model=model, prompt=prompt, api_base=base)
except litellm.exceptions.OpenAIError as e:
    code = getattr(e, "status_code", 500)
    if code == 429:
        retry_with_backoff()
    elif code in (401, 403):
        refresh_credentials()
    elif code == 422:
        fix_request_params(e)  # e.g. Missing model or messages
    else:
        raise

Prevention

When it happens

Trigger: Any failure inside the OpenAI text-completion request path: upstream 4xx/5xx (httpx.HTTPStatusError carries .text), connection errors (message becomes the exception string), timeouts, or the 'Missing model or messages' validation error.

Common situations: Users seeing a wrapped error lose the original exception type; e.g. a 401 from the server shows as OpenAIError with the server's error body text. Common when debugging auth failures, bad api_base, or rate limits on the text-completion path.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/ab9c321cd5c97cc9. Report an issue: GitHub.