BerriAI/litellm · error · MaskedHTTPStatusError

_text (masked response text)

Error message

_text (masked response text)

What it means

Non-streaming sync path of _raise_masked_sync_error: after an httpx.HTTPStatusError on a sync request, litellm extracts the response text, runs it through mask_sensitive_info (strips API keys/tokens), and raises MaskedHTTPStatusError with that masked text. It preserves the original error via __cause__/context while making the message log-safe.

Source

Thrown at litellm/llms/custom_httpx/http_handler.py:467

def _raise_masked_sync_error(e: httpx.HTTPStatusError, stream: bool) -> None:
    """Raise a MaskedHTTPStatusError for sync HTTP handlers."""
    if stream:
        try:
            _body: Final = mask_sensitive_info(
                _safe_read_response(
                    e.response,
                    timeout=_STREAMING_ERROR_BODY_READ_TIMEOUT_SECONDS,
                )
            )
            raise MaskedHTTPStatusError(e, message=_body, text=_body) from None
        finally:
            try:
                e.response.close()
            except Exception:
                pass
    _text: Final = mask_sensitive_info(_safe_get_response_text(e.response))
    raise MaskedHTTPStatusError(e, message=_text, text=_text) from None


async def _raise_masked_async_error(e: httpx.HTTPStatusError, stream: bool) -> None:
    """Raise a MaskedHTTPStatusError for async HTTP handlers."""
    if stream:
        try:
            _body: Final = mask_sensitive_info(
                await _safe_aread_response(
                    e.response,
                    timeout=_STREAMING_ERROR_BODY_READ_TIMEOUT_SECONDS,
                )
            )
            raise MaskedHTTPStatusError(e, message=_body, text=_body) from None
        finally:
            try:
                await e.response.aclose()
            except Exception:
                pass

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Handle httpx.HTTPStatusError / MaskedHTTPStatusError at the call site and branch on status code
  2. Address the upstream cause: credentials, model names, payloads, quotas
  3. Log the masked message safely; do not disable masking in shared log sinks

Example fix

# before
result = litellm.completion(model=..., messages=...)  # surfaces MaskedHTTPStatusError

# after
import httpx
try:
    result = litellm.completion(model=..., messages=...)
except httpx.HTTPStatusError as e:
    logging.warning("upstream %s: %s", e.response.status_code, str(e)[:200])
    raise
Defensive patterns

Strategy: try-catch

Try / catch

import httpx
try:
    result = litellm.completion(...)
except httpx.HTTPStatusError as e:  # MaskedHTTPStatusError subclasses this
    handle_by_status(e.response.status_code)

Prevention

When it happens

Trigger: Any sync HTTPHandler request (completion, embedding, etc.) that returns an HTTP error status — the raise_for_status() failure routes here and the upstream body becomes the exception message.

Common situations: Bad API keys where the provider echoes the key in the error; misrouted api_base producing provider error bodies; quota/billing errors. The masking exists so logged exceptions do not leak credentials.

Related errors


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