BerriAI/litellm · error · TypeError
Unsupported response_format type - {response_format}
Error message
Unsupported response_format type - {response_format} What it means
When converting a response_format into a JSON schema, LiteLLM accepts either a plain dict or a pydantic BaseModel subclass. Anything else — a class that is not a BaseModel (dataclass, TypedDict, attrs, plain class), or an instance instead of the class — raises TypeError('Unsupported response_format type - ...').
Source
Thrown at litellm/llms/base_llm/base_utils.py:190
response_format: type[BaseModel] | dict | None,
ref_template: str | None = None,
) -> dict | None:
"""
Re-implementation of openai's 'type_to_response_format_param' function
Used for converting pydantic object to api schema.
"""
if response_format is None:
return None
if isinstance(response_format, dict):
return _dict_to_response_format_helper(response_format, ref_template)
# type checkers don't narrow the negation of a `TypeGuard` as it isn't
# a safe default behaviour but we know that at this point the `response_format`
# can only be a `type`
if not _parsing._completions.is_basemodel_type(response_format):
raise TypeError(f"Unsupported response_format type - {response_format}")
if ref_template is not None:
schema = response_format.model_json_schema(ref_template=ref_template)
else:
schema = _pydantic.to_strict_json_schema(response_format)
return {
"type": "json_schema",
"json_schema": {
"schema": schema,
"name": response_format.__name__,
"strict": True,
},
}
def map_developer_role_to_system_role(
messages: list[AllMessageValues],View on GitHub (pinned to 6c2dcb801b)
Solutions
- Make response_format a pydantic BaseModel subclass: class Output(BaseModel): ... ; pass Output, not Output()
- Or pass a dict schema directly: response_format={'type':'json_schema','json_schema':{...}}
- For dataclasses/TypedDicts, convert first (e.g. pydantic TypeAdapter(...).json_schema()) or redefine them as BaseModel
- For plain JSON mode use response_format={'type': 'json_object'} (dict form) rather than a non-pydantic class
Example fix
# before
from dataclasses import dataclass
@dataclass
class Output:
answer: str
litellm.completion(model=..., messages=..., response_format=Output)
# after
from pydantic import BaseModel
class Output(BaseModel):
answer: str
litellm.completion(model=..., messages=..., response_format=Output) Defensive patterns
Strategy: type-guard
Validate before calling
from pydantic import BaseModel
def ensure_response_format(rf):
if rf is None or isinstance(rf, dict):
return rf
if isinstance(rf, BaseModel):
rf = type(rf)
if not (isinstance(rf, type) and issubclass(rf, BaseModel)):
raise TypeError(f'response_format must be a BaseModel subclass or dict, got {rf!r}')
return rf Type guard
from pydantic import BaseModel
def is_response_format_valid(rf) -> bool:
if rf is None or isinstance(rf, dict):
return True
if isinstance(rf, BaseModel):
return True
return isinstance(rf, type) and issubclass(rf, BaseModel) Try / catch
try:
litellm.completion(model=m, messages=msgs, response_format=Output)
except TypeError as e:
if 'Unsupported response_format type' in str(e):
# convert dataclass/TypedDict to BaseModel and retry
raise
raise Prevention
- Standardize on pydantic BaseModel subclasses for structured output across the codebase
- Pass the class, never an instance, as response_format
- Add a lint/test that feeds every schema used with response_format through the guard
When it happens
Trigger: Calling completion(..., response_format=MyDataclass) or response_format=SomePydanticModel(**fields) (an instance); passing a TypedDict class or a string like 'json_object' where a schema type is expected; the OpenAI SDK's pydantic classes from a different pydantic version instance.
Common situations: Migrating instructor-style code; mixing pydantic v1/v2 models; passing an enum or Generic alias; assuming OpenAI's response_format={'type':'json_object'} dict shorthand works under a typed API.
Related errors
- litellm.JSONSchemaValidationError: model={model}, returned a
- limit must be an integer
- baseline_model is set for exactly the reverse jobs
- api base needs to be a string. api_base={api_base}
- dynamic_api_key needs to be a string. Got type={type(dynamic
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/36d1cda0937fdbe5.
Report an issue: GitHub.