lfnovo/open-notebook · error · HTTPException

No answer generated

Error message

No answer generated

What it means

500 from /api/search/ask/simple when the ask graph ran to completion but never emitted a 'write_final_answer' chunk, leaving final_answer falsy. The pipeline produced no answer (empty string or None).

Source

Thrown at api/routers/search.py:228

        final_answer = None
        # LangGraph accepts a partial state dict at runtime, but its typed
        # overloads require the full state type (langgraph typing limitation).
        async for chunk in ask_graph.astream(  # type: ignore[call-overload]
            input=dict(question=ask_request.question),
            config=dict(
                configurable=dict(
                    strategy_model=strategy_model.id,
                    answer_model=answer_model.id,
                    final_answer_model=final_answer_model.id,
                )
            ),
            stream_mode="updates",
        ):
            if "write_final_answer" in chunk:
                final_answer = chunk["write_final_answer"]["final_answer"]

        if not final_answer:
            raise HTTPException(status_code=500, detail="No answer generated")

        return AskResponse(answer=final_answer, question=ask_request.question)

    except HTTPException:
        raise
    except OpenNotebookError:
        raise
    except Exception as e:
        logger.error(f"Error in ask simple endpoint: {str(e)}")
        raise HTTPException(status_code=500, detail=f"Ask operation failed: {str(e)}")

View on GitHub (pinned to a7de90d38a)

Solutions

  1. Ingest at least one source and verify search finds it (test /api/search first)
  2. Check logs for whether write_final_answer ran and what it received
  3. Confirm the answer/final models actually return content (test directly)
  4. Upgrade/align versions if the graph definition changed
Defensive patterns

Strategy: fallback

Validate before calling

const kb = await fetch('/api/notes').then(r => r.json()); // or sources count
if (!kb.length) promptIngestFirst();

Try / catch

catch (e) {
  if (e.status === 500 && e.detail === 'No answer generated') suggestIngestAndRetry();
}

Prevention

When it happens

Trigger: POST /api/search/ask/simple where the graph finishes without the write_final_answer node executing or writing a non-empty answer — e.g. retrieval returned nothing and the graph short-circuited, or a model returned an empty response.

Common situations: Empty knowledge base (no ingested sources), all retrieval scores below threshold, LLM returning empty content, graph version mismatch dropping the final node.

Related errors


AI-assisted analysis of lfnovo/open-notebook@a7de90d38a (2026-08-27). Data as JSON: /api/errors/4e7103d617784562. Report an issue: GitHub.