BerriAI/litellm · error · Exception
Invalid response object {traceback.format_exc()} received_a
Error message
Invalid response object {traceback.format_exc()}
received_args={received_args} What it means
The outer except of convert_dict_to_response re-raises any APIError untouched but wraps every other exception in Exception('Invalid response object <full traceback> ... received_args={...}'). It is a catch-all: the real cause is whatever exception the traceback inside the message shows (KeyError on a missing field, ValidationError from pydantic, TypeError from a bad field type, etc.). The received_args dump includes the full response_object, so inspect it to find the malformed field.
Source
Thrown at litellm/litellm_core_utils/llm_response_utils/convert_dict_to_response.py:877
model_response_object.results = response_object["results"]
return model_response_object
except Exception as e:
from litellm.exceptions import APIError
if isinstance(e, APIError):
raise
received_args: Final = dict(
response_object=response_object,
model_response_object=model_response_object,
response_type=response_type,
stream=stream,
start_time=start_time,
end_time=end_time,
convert_tool_call_to_json_mode=convert_tool_call_to_json_mode,
)
raise Exception(f"Invalid response object {traceback.format_exc()}\n\nreceived_args={received_args}")
View on GitHub (pinned to 6c2dcb801b)
Solutions
- Read the embedded traceback in the message string — it names the actual failing field and exception type; fix that field first.
- Inspect received_args.response_object in the message for the offending value's shape.
- Compare the provider payload field-by-field against OpenAI's response schema (types included) and coerce mismatches in your handler.
- If the payload comes from cache, invalidate it and re-fetch.
Example fix
// before (custom handler)
{'choices':[{'message':{'role':'assistant','content':'ok'},'finish_reason':'stop'}], 'usage':{'prompt_tokens':'5','completion_tokens':'7'}} # tokens as strings
# after
{'choices':[{'message':{'role':'assistant','content':'ok'},'finish_reason':'stop'}], 'usage':{'prompt_tokens':5,'completion_tokens':7}} Defensive patterns
Strategy: try-catch
Validate before calling
def looks_like_openai_chat(d: dict) -> bool:
try:
c = d['choices'][0]
return isinstance(c.get('message'), dict)
except (KeyError, IndexError, TypeError):
return False Try / catch
try:
resp = convert_dict_to_response(response_object=d, response_type='completion')
except Exception as e:
if 'Invalid response object' in str(e):
# traceback of the real cause is embedded in the message — log it whole
logging.exception('conversion failed for payload: %r', d)
raise Prevention
- The real cause is inside the embedded traceback — always read the full message before guessing.
- Coerce numeric usage fields to ints in custom handlers.
- Diff provider payloads against OpenAI schemas in CI when integrating new providers.
When it happens
Trigger: A choice dict missing 'message' or 'delta' (KeyError); provider fields with wrong types that pydantic rejects (e.g. usage tokens as strings); unexpected extra keys or nulls in choices; any exception raised by the per-response-type conversion branches above.
Common situations: Custom providers emitting nearly-OpenAI payloads with subtle type mismatches; provider API changes adding/changing field types; cache-replayed responses that lost fields; test fixtures hand-written dicts with typos.
Related errors
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/40326f1a06acc12a.
Report an issue: GitHub.