BerriAI/litellm · error · OpenAIError
error_message or raw_response.text
Error message
error_message or raw_response.text
What it means
Raised as `OpenAIError` on the ChatGPT Responses path when the SSE body could not be parsed into a completed response. `error_message` comes from the SSE extraction helper; if it is empty the raw response text is used instead, and the HTTP status of the original response is preserved. It means the streaming payload was malformed, contained an error event, or the endpoint returned an error page rather than events.
Source
Thrown at litellm/llms/chatgpt/responses/transformation.py:127
raw_response: Any,
logging_obj: Any,
):
body_text: Final = raw_response.text or ""
if not self._should_parse_as_sse(raw_response=raw_response, body_text=body_text):
return super().transform_response_api_response(
model=model,
raw_response=raw_response,
logging_obj=logging_obj,
)
logging_obj.post_call(
original_response=raw_response.text,
additional_args={"complete_input_dict": {}},
)
completed_response, error_message = self._extract_completed_response_from_sse(body_text=body_text)
if completed_response is None:
raise OpenAIError(
message=error_message or raw_response.text,
status_code=raw_response.status_code,
)
self._attach_response_headers(completed_response=completed_response, raw_response=raw_response)
return completed_response
def _should_parse_as_sse(self, raw_response: Any, body_text: str) -> bool:
content_type: Final = (raw_response.headers or {}).get("content-type", "")
if "text/event-stream" in content_type.lower():
return True
trimmed_body: Final = body_text.lstrip()
return bool(
trimmed_body.startswith("event:")
or trimmed_body.startswith("data:")
or "\nevent:" in body_text
or "\ndata:" in body_text
)View on GitHub (pinned to 6c2dcb801b)
Solutions
- Read the message body — it contains either the SSE error text or the raw response, which names the real problem.
- Retry once; truncated streams are often transient network artifacts.
- Disable stream buffering on intermediate proxies (`X-Accel-Buffering: no`, disable response buffering) for `text/event-stream`.
- Upgrade litellm if the ChatGPT responses event schema changed; if persistent, capture the raw body and report it.
Example fix
// before
resp = litellm.responses(model="chatgpt/gpt-4o", input="hi", stream=True)
// after (guard and inspect)
try:
resp = litellm.responses(model="chatgpt/gpt-4o", input="hi", stream=True)
except litellm.llms.openai.common_utils.OpenAIError as e:
logger.error("responses failed status=%s body=%s", e.status_code, e.message)
raise Defensive patterns
Strategy: retry
Try / catch
try:
resp = litellm.responses(model="chatgpt/gpt-4o", input="hi", stream=True)
except OpenAIError as e:
log.error("responses SSE parse failed status=%s body=%.500s", e.status_code, e.message)
if e.status_code in (502, 503, 504):
backoff_and_retry_once()
else:
raise Prevention
- Disable proxy buffering for text/event-stream responses.
- Log the embedded raw body on failure — it names the true cause.
- Keep litellm current so SSE event parsing matches the schema.
When it happens
Trigger: Calling the chatgpt provider's responses endpoint and receiving a non-SSE error body (HTML block page, JSON error) that reaches the SSE parser, or a stream that ends before a terminal/completed event arrives (proxy truncation, connection cut mid-stream).
Common situations: Corporate proxies buffering or truncating event-streams; model/parameter combos the ChatGPT backend rejects mid-stream; account/session errors surfacing as error events; outdated litellm SSE parsing against a changed event schema.
Related errors
- Error parsing chunk: {e}, Received chunk: {chunk}
- Chunk does not start with 'data:': {chunk}
- Chunk cannot be parsed as JSON: {e}
- Unexpected responses stream payload
- Stream ended without a completed response
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/fd2e5fa192dbcb07.
Report an issue: GitHub.