BerriAI/litellm · error · ValueError
Stream completed response is invalid
Error message
Stream completed response is invalid
What it means
Raised by the sync stream-collection path of the chat-completions-to-Responses-API bridge. After the stream is fully drained, the handler reads stream_iter.completed_response.response, coerces it via _coerce_response_object, and requires the result to be a ResponsesAPIResponse. If coercion succeeds but the object still fails the isinstance check, the completed payload is malformed. In practice this is a defensive guard: it fires only on litellm internal bugs, version skew, or exotic custom stream wrappers.
Solutions
- Retry the same call with stream=False so the non-streaming bridge path is used, to confirm the model itself works
- Upgrade litellm to the latest patch release (bridge/stream-wrapper contract fixes land frequently)
- Inspect stream_iter.completed_response and its .response in a debugger right after iteration to see what object was accumulated
- If you pass a custom stream wrapper, ensure it sets completed_response.response to a ResponsesAPIResponse-shaped object before exhaustion
- File a litellm issue with the model, provider, and stream payload if it reproduces on the latest version
Example fix
// before resp = bridge_handler.completion(**kwargs, stream=True) # ValueError: Stream completed response is invalid // after resp = litellm.completion(model=model, messages=messages, stream=False) # bypass stream collection while debugging
Defensive patterns
Strategy: try-catch
Type guard
from litellm.types.llms.openai import ResponsesAPIResponse
def has_valid_completed_response(stream_iter) -> bool:
completed = getattr(stream_iter, "completed_response", None)
resp = getattr(completed, "response", None) if completed else None
return isinstance(resp, ResponsesAPIResponse) or isinstance(resp, dict) Try / catch
try:
resp = litellm.completion(model=m, messages=msgs, stream=True)
except ValueError as e:
if "Stream completed response is invalid" in str(e):
resp = litellm.completion(model=m, messages=msgs, stream=False) # non-stream fallback
else:
raise Prevention
- Keep litellm upgraded so the stream wrapper and bridge share one contract
- If you inject custom stream wrappers, always set completed_response.response before exhaustion
- Smoke-test streaming paths after every litellm upgrade
When it happens
Trigger: litellm.completion(..., stream=True) on a model routed through the responses bridge where the CustomStreamWrapper finishes without a well-formed completed_response.response object (e.g. a custom_llm_provider stream wrapper, a cached_response stream, or a partially-accumulated completed object after early termination).
Common situations: Custom providers or proxies that return their own stream iterators without completed_response; mocked/fake streams in tests; mixing litellm versions where the wrapper no longer populates completed_response; debugging sessions that intercept the stream.
Related errors
- Chat provider: Invalid chunk type
- Unexpected response type
- Chat provider: Empty parsed_chunk
- Chat provider: Invalid function argument delta
- model is required
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/9307e5b2380ea6c6.
Report an issue: GitHub.
Appendix: source
Thrown at litellm/completion_extras/litellm_responses_transformation/handler.py:84
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")
hidden_params: Final = getattr(stream_iter, "_hidden_params", None)
response: Final = self._coerce_response_object(response_obj, hidden_params)
if not isinstance(response, ResponsesAPIResponse):
raise ValueError("Stream completed response is invalid")
return response
async def _collect_response_from_stream_async(self, stream_iter: Any) -> "ResponsesAPIResponse":
async 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")
hidden_params: Final = getattr(stream_iter, "_hidden_params", None)
response: Final = self._coerce_response_object(response_obj, hidden_params)
if not isinstance(response, ResponsesAPIResponse):
raise ValueError("Stream completed response is invalid")
return response
def validate_input_kwargs(self, kwargs: dict) -> ResponsesToCompletionBridgeHandlerInputKwargs:View on GitHub (pinned to 77b7c6c40c)