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

  1. Print type(result.output_obj) to identify the actual type returned by the query engine.
  2. Ensure the pydantic BaseModel used for output_cls and the one imported in summary.py come from the same pydantic major version (v2 everywhere).
  3. If the engine returns a dict, construct the model explicitly: output_cls(**response.response) before setting output_obj.
  4. 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

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


AI-assisted analysis of zylon-ai/private-gpt@4a030776a3 (2026-08-15). Data as JSON: /api/errors/3f7f693708bbe771. Report an issue: GitHub.