BerriAI/litellm · error · BytezError

e.response.text

Error message

e.response.text

What it means

In the synchronous streaming path, the POST to Bytez is wrapped in `except httpx.HTTPStatusError` which re-raises as BytezError carrying e.response.status_code and the response body text. In practice httpx only raises HTTPStatusError when raise_for_status() is invoked, so the adjacent `status_code != 200` check is the more common path — but either way an HTTP error on the streaming request surfaces as BytezError with the raw body as the message.

Source

Thrown at litellm/llms/bytez/chat/transformation.py:274

        messages: list,
        client: HTTPHandler | AsyncHTTPHandler | None = None,
        json_mode: bool | None = None,
        signed_json_body: bytes | None = None,
    ) -> "BytezCustomStreamWrapper":
        if client is None or isinstance(client, AsyncHTTPHandler):
            client = _get_httpx_client(params={})

        try:
            response: Final = client.post(
                api_base,
                headers=headers,
                data=json.dumps(data),
                stream=True,
                logging_obj=logging_obj,
                timeout=STREAMING_TIMEOUT,
            )
        except httpx.HTTPStatusError as e:
            raise BytezError(status_code=e.response.status_code, message=e.response.text)

        if response.status_code != 200:
            raise BytezError(status_code=response.status_code, message=response.text)

        completion_stream: Final = response.iter_text()

        streaming_response: Final = BytezCustomStreamWrapper(
            completion_stream=completion_stream,
            model=model,
            custom_llm_provider=custom_llm_provider,
            logging_obj=logging_obj,
        )
        return streaming_response

    @track_llm_api_timing()
    async def get_async_custom_stream_wrapper(
        self,
        model: str,

View on GitHub (pinned to 77b7c6c40c)

Solutions

  1. Catch BytezError, log status_code, and branch on it (auth vs rate-limit vs server).
  2. Fix the underlying cause the body text reveals (bad key, bad model URL, quota).
  3. Add retry with exponential backoff for 429/5xx status codes.
  4. For long error bodies, truncate before logging to keep logs readable.
Defensive patterns

Strategy: try-catch

Try / catch

from litellm.llms.bytez.common_utils import BytezError
import time

for attempt in range(3):
    try:
        stream = litellm.completion(model="bytez/org/model", messages=msgs, stream=True)
        break
    except BytezError as e:
        if e.status_code in (429, 502, 503) and attempt < 2:
            time.sleep(2 ** attempt)
            continue
        raise

Prevention

When it happens

Trigger: stream=True request rejected at the HTTP layer: 401 bad key, 404 wrong model path/URL, 429 rate limit, 5xx from Bytez — the response body text becomes the error message.

Common situations: Expired/rotated keys producing 401 HTML/JSON bodies; rate limits during batch jobs; wrong api_base; Bytez incidents returning 502/503 pages that end up verbatim in the exception message.

Understand the failure class

Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.

Related errors


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