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
- Catch BytezError, log status_code, and branch on it (auth vs rate-limit vs server).
- Fix the underlying cause the body text reveals (bad key, bad model URL, quota).
- Add retry with exponential backoff for 429/5xx status codes.
- 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
- Branch on status_code instead of parsing the raw body text from the message.
- Truncate e.message to a few hundred chars before logging — error pages can be huge.
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
- response.text
- A2A send_message_streaming failed: no response received afte
- api_base is required for Pydantic AI agents
- Stream completed response is invalid
- Chat provider: Empty parsed_chunk
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/5f262ebc27e0567a.
Report an issue: GitHub.