zylon-ai/private-gpt · error · TypeError
Expected output object to be a BaseModel, got {type(response
Error message
Expected output object to be a BaseModel, got {type(response)} What it means
Type-check in run_summary: result.output_obj exists but is not an instance of pydantic BaseModel, so calling model_dump_json() on it would fail. This indicates the workflow returned an object of an unexpected type in the structured-output path — e.g. a dict, a LlamaIndex structured output wrapper, or an object from a different pydantic major version (v1 vs v2).
Source
Thrown at private_gpt/components/workflows/others/summary.py:129
try:
handler = self.run(
start_event=SummarizeInputEvent(
model_id=model_id,
prompt=prompt,
instructions=instructions,
additional_instructions=additional_instructions,
output_cls=output_cls,
empty_response_fallback=empty_response_fallback,
)
)
result: SummarizeResultEvent = await handler
if output_cls:
response = result.output_obj
if not response:
raise ValueError("No output object was generated")
if not isinstance(response, BaseModel):
raise TypeError(
f"Expected output object to be a BaseModel, got {type(response)}"
)
return [TextBlock(text=response.model_dump_json())]
else:
summary = result.summary
summary_text = summary if isinstance(summary, str) else None
if not summary_text:
raise ValueError("No summary was generated")
return [TextBlock(text=summary_text)]
except asyncio.CancelledError as e:
if handler:
await handler.cancel_run()
raise e
async def _generate_prompt_template(
self,View on GitHub (pinned to 4a030776a3)
Solutions
- Print type(result.output_obj) to identify the actual type returned by the query engine.
- Ensure the pydantic BaseModel used for output_cls and the one imported in summary.py come from the same pydantic major version (v2 everywhere).
- If the engine returns a dict, construct the model explicitly: output_cls(**response.response) before setting output_obj.
- Align llama-index structured-output configuration so it returns a pydantic v2 model instance.
Example fix
# before output_obj=engine_response.response # may be a dict # after raw = engine_response.response output_obj = raw if isinstance(raw, BaseModel) else output_cls(**raw)
Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(result.output_obj, BaseModel):
result.output_obj = output_cls(**dict(result.output_obj)) Type guard
from pydantic import BaseModel
def is_pydantic_model(obj: object) -> bool:
return isinstance(obj, BaseModel) Try / catch
try:
blocks = await wf.run_summary(prompt=p, output_cls=Cls)
except TypeError as e:
if 'BaseModel' in str(e):
# re-wrap dicts into the model and continue
... Prevention
- Pin one pydantic major version across the project and llama-index extras
- Construct output_obj from output_cls explicitly at the source
- Type SummarizeResultEvent.output_obj strictly and let pydantic validate on event creation
When it happens
Trigger: output_cls requested but the query engine populated output_obj with a dict or other non-BaseModel; mixing pydantic v1 models (llama_index legacy) with a v2 codebase; monkeypatched/mocked SummarizeResultEvent that sets output_obj to a plain object.
Common situations: Upgrading llama-index / pydantic major versions where structured output objects changed type; test doubles that bypass pydantic validation; serializing the engine response manually into output_obj.
Related errors
- Schema must define a 'type' field
- Array schemas must define 'items'
- Array 'items' must be a dictionary representing JSON Schema
- Object schemas must define 'properties'
- Expected list or dict with 'items' key, got {type(obj)}
AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15).
Data as JSON: /api/errors/3f7f693708bbe771.
Report an issue: GitHub.