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

  1. Update litellm — bridge payload handling is actively fixed across versions: pip install -U litellm
  2. If the payload comes from a custom transformation, ensure it returns a dict or ResponsesAPIResponse on completed_response.response
  3. 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

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


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/5ecb20056fc06ec8. Report an issue: GitHub.