BerriAI/litellm · error · ValueError
Unexpected responses stream payload
Error message
Unexpected responses stream payload
What it means
This handler bridges the Responses API to a completion-style stream by replaying the stream iterator and collecting its final completed_response. When the collected payload's response object is neither a ResponsesAPIResponse nor a dict (e.g. a string, bytes, or some provider-specific object), _coerce_response_object raises ValueError('Unexpected responses stream payload'). It is an internal invariant violation: upstream code produced a payload the bridge cannot convert.
Source
Thrown at litellm/completion_extras/litellm_responses_transformation/handler.py:61
def _is_preformatted_cached_chat_stream(result: Any) -> bool:
from litellm.litellm_core_utils.streaming_handler import CustomStreamWrapper
return isinstance(result, CustomStreamWrapper) and result.custom_llm_provider == "cached_response"
@staticmethod
def _coerce_response_object(
response_obj: Any,
hidden_params: dict | None,
) -> "ResponsesAPIResponse":
if isinstance(response_obj, ResponsesAPIResponse):
response = response_obj
elif isinstance(response_obj, dict):
try:
response = ResponsesAPIResponse(**response_obj)
except Exception:
response = ResponsesAPIResponse.model_construct(**response_obj)
else:
raise ValueError("Unexpected responses stream payload")
if hidden_params:
existing: Final = getattr(response, "_hidden_params", None)
if not isinstance(existing, dict) or not existing:
setattr(response, "_hidden_params", dict(hidden_params))
else:
for key, value in hidden_params.items():
existing.setdefault(key, value)
return response
def _collect_response_from_stream(self, stream_iter: Any) -> "ResponsesAPIResponse":
for _ in stream_iter:
pass
completed: Final = getattr(stream_iter, "completed_response", None)
response_obj: Final = getattr(completed, "response", None) if completed else None
if response_obj is None:
raise ValueError("Stream ended without a completed response")View on GitHub (pinned to 6c2dcb801b)
Solutions
- Update litellm — bridge payload handling is actively fixed across versions: pip install -U litellm
- If the payload comes from a custom transformation, ensure it returns a dict or ResponsesAPIResponse on completed_response.response
- Reproduce with litellm.responses(stream=True) against the same model/provider and inspect the type of stream.completed_response.response to identify the offending layer
Defensive patterns
Strategy: type-guard
Type guard
from litellm.types.responses import ResponsesAPIResponse
def is_coercible_response_payload(obj: Any) -> TypeGuard[ResponsesAPIResponse | dict]:
return isinstance(obj, (ResponsesAPIResponse, dict)) Try / catch
try:
result = bridge.collect(stream_iter)
except ValueError as e:
if 'Unexpected responses stream payload' in str(e):
logger.error('Provider produced a non-standard completed response payload: %r', type(payload))
raise Prevention
- Update litellm when bridging new providers — payload coercion is actively maintained
- In custom transformations, always materialize completed_response.response as a dict or ResponsesAPIResponse
When it happens
Trigger: Using the responses-to-completion bridge (e.g. litellm.responses(...) with a completion-style consumer) where a provider transformation yields completed_response.response of an unexpected type; typically surfaces with nonstandard providers or custom transformation hooks.
Common situations: Beta/edge providers whose transformation layers return raw strings or provider objects instead of the expected dict/model; version skew between litellm core and a provider adapter.
Related errors
- Stream ended without a completed response
- Stream completed response is invalid
- tool call not supported: {tool_call}
- chunk is not a string: {chunk}
- Failed to convert ModelResponse to ModelResponseStream: {mod
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/5ecb20056fc06ec8.
Report an issue: GitHub.