BerriAI/litellm · error · ValueError
Unexpected response type: {type(raw_response)}
Error message
Unexpected response type: {type(raw_response)} What it means
transform_response raises this when the object passed as raw_response is not a litellm ResponsesAPIResponse. This method is the Responses→chat-completions converter used by the bridge; feeding it a raw httpx.Response, a plain dict, or an OpenAI SDK response object instead of the parsed ResponsesAPIResponse trips this guard.
Source
Thrown at litellm/completion_extras/litellm_responses_transformation/transformation.py:742
self,
model: str,
raw_response: "BaseModel",
model_response: "ModelResponse",
logging_obj: "LiteLLMLoggingObj",
request_data: dict,
messages: list["AllMessageValues"],
optional_params: dict,
litellm_params: dict,
encoding: object,
api_key: str | None = None,
json_mode: bool | None = None,
) -> "ModelResponse":
"""Transform Responses API response to chat completion response"""
from litellm.responses.utils import ResponseAPILoggingUtils
from litellm.types.llms.openai import ResponsesAPIResponse
if not isinstance(raw_response, ResponsesAPIResponse):
raise ValueError(f"Unexpected response type: {type(raw_response)}")
if raw_response.error is not None:
raise ValueError(f"Error in response: {raw_response.error}")
output_items = raw_response.output
if len(output_items) == 0:
recovered_output_items: Final = self._recover_output_items_from_logging(logging_obj)
if recovered_output_items:
output_items = cast(Any, recovered_output_items)
raw_response.output = cast(Any, recovered_output_items)
verbose_logger.warning(
"Recovered empty Responses API output from raw SSE for model=%s",
model,
)
# Convert response output to choices using the static helper
choices: Final = self._convert_response_output_to_choices(
output_items=output_items,View on GitHub (pinned to 6c2dcb801b)
Solutions
- Parse the payload first: ResponsesAPIResponse(**json_body) before calling transform_response
- Let litellm's own provider adapter do the parsing — do not call transform_response with transport-level objects
- In tests, construct fixtures as ResponsesAPIResponse instances or validated dicts
Example fix
# before resp = await client.post(url, json=payload) model_resp = handler.transform_response(resp.json(), ...) # raw dict # after from litellm.types.llms.openai import ResponsesAPIResponse parsed = ResponsesAPIResponse(**resp.json()) model_resp = handler.transform_response(parsed, ...)
Defensive patterns
Strategy: type-guard
Validate before calling
from litellm.types.llms.openai import ResponsesAPIResponse
def is_parsed_responses_payload(raw) -> bool:
return isinstance(raw, ResponsesAPIResponse) Type guard
from litellm.types.llms.openai import ResponsesAPIResponse
def is_responses_api_response(v) -> bool:
return isinstance(v, ResponsesAPIResponse) Prevention
- Always run ResponsesAPIResponse(**body) before transform_response
- Never hand transport-level objects (httpx.Response, raw dicts) to transformers
When it happens
Trigger: Calling LiteLLMResponsesTransformationHandler.transform_response (or the bridge) with the unparsed HTTP body or an SDK object; a provider adapter returning the raw JSON dict instead of validating it into ResponsesAPIResponse first.
Common situations: Custom provider integrations that skip the schema validation step; tests passing fixtures as dicts; refactors that changed what the transport returns.
Related errors
- tool call not supported: {tool_call}
- {model} unable to complete request: {raw_response.incomplete
- Unknown items in responses API response: {output_items}
- Invalid value passed in for aget_assistants. Only bool or No
- Invalid value passed in for async_create_assistants. Only bo
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/bb6a5ca96d60c7de.
Report an issue: GitHub.