zylon-ai/private-gpt · error · ValueError

No response was generated

Error message

No response was generated

What it means

Inside the workflow step execute_summarize: the query engine returned a PydanticResponse (because output_cls was set) but its .response payload is falsy — the structured-output model instance is None/empty. The step refuses to emit SummarizeResultEvent(output_obj=...) with nothing in it, surfacing the failure early instead of at the caller.

Source

Thrown at private_gpt/components/workflows/others/summary.py:226

            user_query=ev.instructions,
            additional_instructions="\n".join(ev.additional_instructions or []),
            max_words=int(max_tokens * 0.75),
        )

        logger.debug(f"Executing summarization with max_tokens: {max_tokens}")
        task = asyncio.create_task(query_engine.aquery(template.format()))
        try:
            response = await task
        except asyncio.CancelledError:
            logger.info("Summarization task was cancelled")
            task.cancel()
            raise

        logger.debug("Summarization completed successfully")

        if ev.output_cls and isinstance(response, PydanticResponse):
            if not response.response:
                raise ValueError("No response was generated")

            return SummarizeResultEvent(
                output_obj=response.response,
            )

        if isinstance(response, Response):
            summary = response.response or ev.empty_response_fallback or ""
            if not summary:
                raise ValueError("No summary was generated")

            sanitized = MarkdownHelper.sanitize_markdown(summary)
            return SummarizeResultEvent(summary=sanitized or summary)

        elif isinstance(response, StreamingResponse):
            raise NotImplementedError(
                "Streaming responses are not yet implemented for summarization"
            )

View on GitHub (pinned to 4a030776a3)

Solutions

  1. Log the raw LLM output for the summary prompt and compare against output_cls — loosen the schema (make fields optional with defaults) if parsing fails.
  2. Verify the retriever actually returns nodes (the same message hints 'Ensure the retriever returns nodes') and that context reaches the prompt.
  3. Upgrade/align llama-index so PydanticResponse.response is reliably populated on successful parses.
  4. Retry with a more explicit instruction to output JSON conforming to the schema.

Example fix

# before
class Summary(BaseModel):
    title: str
    bullets: list[str]

# after
class Summary(BaseModel):
    title: str = ""
    bullets: list[str] = Field(default_factory=list)
Defensive patterns

Strategy: fallback

Validate before calling

if ev.output_cls and isinstance(response, PydanticResponse) and not response.response:
    return SummarizeResultEvent(summary=ev.empty_response_fallback or "")

Type guard

def valid_pydantic_response(r: object) -> bool:
    return isinstance(r, PydanticResponse) and r.response is not None

Try / catch

try:
    result = await handler
except ValueError as e:
    if 'No response was generated' in str(e):
        result = await retry_with_looser_schema()

Prevention

When it happens

Trigger: Query engine configured with response_mode producing PydanticResponse but the LLM output failed schema parsing, yielding an empty structured object; output_cls registered on the engine while the model returned empty content; edge case where synthesize() constructs an empty PydanticResponse.

Common situations: Structured summarization with a schema the model cannot satisfy; empty retrieval context producing empty generations; llama-index version changes in how failed structured parses are represented.

Related errors


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