{"record":{"id":"8427517186635253","repo":"BerriAI/litellm","slug":"text-masked-response-text","errorCode":null,"errorMessage":"_text (masked response text)","messagePattern":"_text \\(masked response text\\)","errorType":"http","errorClass":"MaskedHTTPStatusError","httpStatus":null,"severity":"error","filePath":"litellm/llms/custom_httpx/http_handler.py","lineNumber":467,"sourceCode":"\ndef _raise_masked_sync_error(e: httpx.HTTPStatusError, stream: bool) -> None:\n    \"\"\"Raise a MaskedHTTPStatusError for sync HTTP handlers.\"\"\"\n    if stream:\n        try:\n            _body: Final = mask_sensitive_info(\n                _safe_read_response(\n                    e.response,\n                    timeout=_STREAMING_ERROR_BODY_READ_TIMEOUT_SECONDS,\n                )\n            )\n            raise MaskedHTTPStatusError(e, message=_body, text=_body) from None\n        finally:\n            try:\n                e.response.close()\n            except Exception:\n                pass\n    _text: Final = mask_sensitive_info(_safe_get_response_text(e.response))\n    raise MaskedHTTPStatusError(e, message=_text, text=_text) from None\n\n\nasync def _raise_masked_async_error(e: httpx.HTTPStatusError, stream: bool) -> None:\n    \"\"\"Raise a MaskedHTTPStatusError for async HTTP handlers.\"\"\"\n    if stream:\n        try:\n            _body: Final = mask_sensitive_info(\n                await _safe_aread_response(\n                    e.response,\n                    timeout=_STREAMING_ERROR_BODY_READ_TIMEOUT_SECONDS,\n                )\n            )\n            raise MaskedHTTPStatusError(e, message=_body, text=_body) from None\n        finally:\n            try:\n                await e.response.aclose()\n            except Exception:\n                pass","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/custom_httpx/http_handler.py#L449-L485","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Handle httpx.HTTPStatusError / MaskedHTTPStatusError at the call site and branch on status code","Address the upstream cause: credentials, model names, payloads, quotas","Log the masked message safely; do not disable masking in shared log sinks"],"exampleFix":"# before\nresult = litellm.completion(model=..., messages=...)  # surfaces MaskedHTTPStatusError\n\n# after\nimport httpx\ntry:\n    result = litellm.completion(model=..., messages=...)\nexcept httpx.HTTPStatusError as e:\n    logging.warning(\"upstream %s: %s\", e.response.status_code, str(e)[:200])\n    raise","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"import httpx\ntry:\n    result = litellm.completion(...)\nexcept httpx.HTTPStatusError as e:  # MaskedHTTPStatusError subclasses this\n    handle_by_status(e.response.status_code)","preventionTips":["Catch httpx.HTTPStatusError once at the service boundary and normalize to your app's error type","Rely on litellm's masking instead of logging raw URLs/bodies yourself"],"tags":["http","masking","error-handling","litellm"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}