Skip to content

llm-worker: DailyReport structured output is disabled — Ollama rejects its JSON schema with a grammar-parse error #1748

Description

@Xore

Splitting this out of a comment on #1660, which is closed — so today this is only tracked in prose on a closed issue, and the daily report has been silently off since 2026-08-22.

Current state

LLM_DAILY_REPORT_ENABLED=false on the live hp-llm-worker. The session and payload pipelines run normally against real captured data; the daily report does not run at all.

The failure

analyze_daily_report() passes DailyReport.model_json_schema() as Ollama's format. Ollama answers:

400 "Failed to initialize samplers: failed to parse grammar"

Deterministic, and independent of prompt content — it reproduces directly against /api/chat with a trivial prompt. PayloadAnalysis and SessionAnalysis use the same code path and work fine.

What is known

An earlier bisect found that a summary string plus a single enum field is enough to reproduce it, while the full 7-field PayloadAnalysis schema — more fields, larger arrays — is not. That rules out "too many fields" and points at a specific construct rather than anything wrong with DailyReport's field types.

Comparing the two schemas, the differences are narrow:

PayloadAnalysis (works) DailyReport (fails)
summary maxLength: 1200 maxLength: 2000
lists 10 / 20 / 50 items three × 20 items

Ollama compiles the JSON schema into a GBNF grammar, and bounded-length strings become repetition rules. A large maxLength is a plausible way to blow past a limit in that compiler — which would explain why the trigger is a size, not a field.

What a fix needs

Either shape the schema so Ollama's grammar compiler accepts it, or stop constraining this one call site and validate the reply in Python instead. Whichever it is, the bound belongs in the Pydantic validator regardless — the schema is what asks the model to behave, the validator is what actually enforces it.

Then re-enable LLM_DAILY_REPORT_ENABLED and confirm a real report is written to the llm-analysis index.

Why it matters

This is the only one of the three annotation pipelines that has never produced a single real output. It was never exercised before captured-data mode was turned on, so it has been broken from the start rather than regressed.

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingllmLLM analysis worker

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions