Skip to content
[bmdpat]
All writing
5 min read

Ollama JSON: Empty Results Are Not Failed Requests

An empty Ollama result can mean no matches or a broken request. I test the response parser so local extraction failures cannot pass as clean results.

Share LinkedIn

I want my local extractor to say when it failed. Returning an empty list after a broken request hides the one fact I need.

An empty result is valid only after the request finishes and the response passes the application's checks. A timeout, invalid JSON, or missing field must remain a failure. JSON syntax alone cannot tell you whether the model found every item in the source.

Canonical URL: https://bmdpat.com/blog/ollama-json-empty-result-vs-failed-request-2026

Where does this affect my local stack?

My local model routing post describes separate prose and structured-data jobs. This post tests a smaller part of that system: the code that accepts an extraction result before another task uses it.

On September 13, 2026, I tested the Python function below with fixed response objects. These are test fixtures, not captured model outputs or a model accuracy benchmark. They let me check the caller's behavior without loading a model, changing a quant, or spending another inference request.

The target job is deliberately small. Given a note, extract a list of names. A note with no names can produce an empty list. A broken response cannot justify the same result.

Accept completed responses with valid fields; preserve empty results and errors as separate outcomes

What does Ollama return around the JSON?

For this example I use the native /api/generate response shape. Ollama documents response as the generated text and done as the completion flag. Its format field accepts JSON mode or a JSON schema. The endpoint streams by default; this example assumes the caller requests stream: false.

There are two objects to check. The outer object comes from the API. The inner JSON text comes from the model. Parsing the HTTP body does not also parse the text inside response.

I would pass an object schema with a required names array whose items are strings. Ollama's structured output guide shows how to request a schema and then validate the returned text. I still need application checks before the list reaches a downstream task.

How do I keep an empty result separate from failure?

Here is the complete acceptance function for the small example. It expects the decoded API object after the caller checks HTTP status. Transport errors must propagate before this function runs.

import json def accept_names(reply): if not isinstance(reply, dict): raise ValueError("API response must be an object") if "error" in reply or reply.get("done") is not True: raise ValueError("Generation failed or is incomplete") raw = reply.get("response") if not isinstance(raw, str): raise ValueError("Missing generated text") result = json.loads(raw) if not isinstance(result, dict) or set(result) != {"names"}: raise ValueError("Expected only the names field") names = result["names"] if not isinstance(names, list): raise ValueError("Names must be a list") if any(not isinstance(name, str) or not name.strip() for name in names): raise ValueError("Each name must be non-empty text") return names

Python's json.loads raises JSONDecodeError for invalid JSON. I let that exception reach the caller. I do not catch it and return [].

An empty list passes this function when the response contains the exact expected object. A missing list fails. A string in place of a list fails. A blank name fails. These are different inputs with different outcomes, even when the dashboard would otherwise show the same empty table.

Which cases did I test?

The passing fixtures contain an empty names list and a names list with Ada. The failing fixtures cover an API error, an incomplete response, absent generated text, malformed JSON, a missing field, the wrong field type, a blank name, and an unexpected extra field.

I also tested a decoded API value that is a list instead of an object, and a generated JSON value that is a list. Both fail. That matters because valid JSON includes values other than the object my application expects.

The fixture checks establish parser behavior. They do not establish that any local model will extract names correctly. Keep those results in separate test reports so a passing unit test cannot become an invented model score.

What can this check still miss?

A completed response can contain valid JSON and still omit Ada from a note that names her. This function would accept that empty list. To test extraction quality, use source fixtures with known expected names and compare the returned list against them.

Completion also deserves its own check. Keep the recorded stop reason with the response, as I explain in my stop-reason post. The function above checks the completion flag; it does not prove the model finished the intended task.

My practical rule is to preserve the failure at the boundary. Save the error category and enough redacted context to reproduce it. Let the caller choose a bounded retry or a visible failure. A blank result should mean the extraction returned no names, with its accuracy still subject to the task test.

Accompanying prompt

What the prompt does: Adds separate tests for valid empty output, request failure, and extraction accuracy in a local Ollama client.

Copy/paste this prompt:

Copy-ready prompt

Paste the exact block into your coding agent.

No article chrome, no footnotes, no formatting drift.

Role: You review a local Ollama extraction client. Context: I will paste the request code, parser, and schema. Task: Find every path that converts failure into empty output. Output: Show a small fix and tests for valid empty results, malformed responses, request failures, and known source answers. Constraints: Keep the existing storage format. Do not call a model. Use fixed fixtures. Separate parser tests from accuracy tests. Do not claim that schema validation proves correctness.
8 lines485 chars
Ready

This prompt and every other one we publish live in the free prompt library.

Copy the block above.

I publish local AI tests and failure reports in The 5090 Reports. Join the email list for the next report.

Get the Local AI Field Kit

Four copy-ready tools now, then one evidence-backed Local AI Lab Note on Friday when there is something worth sharing.

Try the free agent run check first

Get the requested artifact now, then at most one evidence-backed Local AI Lab Note on Friday when there is something worth sharing. One-click unsubscribe. No sponsored placements. Privacy.

PH

Patrick Hughes

I build BMD and publish measured AI runs, failure reports, and reusable checks. Nashville, Tennessee.

More writing