BerriAI/litellm · error · ValueError
Chat provider: Empty parsed_chunk
Error message
Chat provider: Empty parsed_chunk
What it means
The chunk transformer raises when handed an empty/falsy parsed_chunk (None, empty dict). This method converts Responses API stream events into chat.completion.chunk objects for callers bridging a Responses stream into the chat-completions streaming shape; an empty event means the upstream event deserialization or a custom generator produced nothing.
Source
Thrown at litellm/completion_extras/litellm_responses_transformation/transformation.py:1221
parsed_chunk: Dict containing the Responses API event chunk
tool_call_index_map: Per-stream output_index -> sequential tool_call index map
Returns:
ModelResponseStream: OpenAI-formatted streaming chunk
Raises:
ValueError: If chunk is invalid or missing required fields
"""
from litellm.types.llms.openai import ChatCompletionToolCallFunctionChunk
from litellm.types.utils import (
ChatCompletionToolCallChunk,
Delta,
ModelResponseStream,
StreamingChoices,
)
if not parsed_chunk:
raise ValueError("Chat provider: Empty parsed_chunk")
if isinstance(parsed_chunk, BaseModel):
parsed_chunk = parsed_chunk.model_dump()
if not isinstance(parsed_chunk, dict):
raise ValueError(f"Chat provider: Invalid chunk type {type(parsed_chunk)}")
# Handle different event types from responses API
event_type = parsed_chunk.get("type")
if isinstance(event_type, ResponsesAPIStreamEvents):
event_type = event_type.value
if parsed_chunk.get("object") == "chat.completion.chunk" or (
event_type is None and isinstance(parsed_chunk.get("choices"), list) and parsed_chunk.get("choices")
):
return ModelResponseStream(**parsed_chunk)
verbose_logger.debug("Chat provider: Processing event type: %s", event_type)
View on GitHub (pinned to 6c2dcb801b)
Solutions
- Skip empty events before transformation: `if not chunk: continue` in your generator
- If parsing SSE yourself, ignore comment lines (`:` prefix) and non-event frames instead of yielding empty dicts
- Log the raw event stream to find which frame produced the empty chunk
Example fix
# before
for chunk in sse_parser(raw_stream):
transformed = transformer.chunk_parser(chunk) # chunk may be {}
# after
for chunk in sse_parser(raw_stream):
if not chunk:
continue
transformed = transformer.chunk_parser(chunk) Defensive patterns
Strategy: validation
Validate before calling
def chunk_nonempty(chunk) -> bool:
return bool(chunk) Try / catch
for raw in event_source:
if not raw:
continue # skip keep-alives/empties
out = transformer.chunk_parser(raw, ...) Prevention
- Skip falsy events in your stream generator
- Ignore SSE comment lines and non-data frames when parsing manually
When it happens
Trigger: A generator feeding the transformer yields None or {} — e.g. a custom SSE parser that emits empty placeholders on keep-alive/comment events, or middleware filtering events down to nothing.
Common situations: Custom streaming adapters between provider SSE and the bridge; proxies forwarding comment-only SSE lines as empty dicts; test fixtures with empty event dicts.
Related errors
- Chat provider: Invalid chunk type {type(parsed_chunk)}
- Chat provider: Invalid function argument delta {parsed_chunk
- Chat provider: Invalid text delta {parsed_chunk}
- Braintrust API error: {e.response.text}
- Failed to connect to Braintrust API: {str(e)}
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/2837748520485553.
Report an issue: GitHub.