My Local LLM Writer Failed Its Own Word-Count Gate
Gemma 4 26B wrote a 535-word draft against a 550-word floor. The gate blocked it, both rescue engines were down, and no bad post shipped.
TL;DR
- On 2026-08-17 a local blog writer, Gemma 4 26B via Ollama on an RTX 5090, produced a 535-word draft against a 550-word floor, so a deterministic output gate rejected it.
- The 07:45 run never loaded the model because the host RAM guard wants 16 GiB free before a Gemma cold load. The 10:00 run loaded and failed: body word count 535 outside 550-1100.
- Both frontier rescue engines were down, one on quota and one on expired auth. The result was 0 posts shipped and 0 bad posts shipped.
Every morning a local model writes my blog draft. Gemma 4 26B runs through Ollama on an RTX 5090 and hands its output to a deterministic gate before anything reaches the publish queue. On 2026-08-17 the gate said no, twice, and the pipeline shipped nothing. That is the system working. It still cost me a publish day, so here is the full failure chain and what I changed.
Summary: On 2026-08-17 a local blog writer (Gemma 4 26B via Ollama on an RTX 5090) produced a 535-word draft against a 550-word floor, so a deterministic output gate rejected it. Both frontier rescue engines were down at the same time, one on quota and one on expired auth. The result was 0 posts shipped and 0 bad posts shipped.

What failed in the local writer run?
Two separate things, in order.
The 07:45 run never loaded the model. The host RAM guard wants 16 GiB free before a Gemma cold load, and the box had less. The run exited with a skip reason instead of grinding the machine into swap. If you run big models next to real workloads, you want this guard. I covered the memory side of this in unload local LLMs after tests.
The 10:00 run loaded fine and generated. Then the output gate counted the body: 535 words against a 550 to 1100 window. The draft also failed a literal-string check for the closing prompt section my blog contract requires. The writer exited nonzero and wrote nothing to the queue.
The word count check is one line of Python: len(body.split()). It catches a real failure mode. A 26B model will write a confident, complete-looking draft and stop early. Nothing about the text looks broken. Only the count says so. I saw the same shape in my 4B vs 26B task quality tests: small and mid-size local models fail quietly, not loudly.
Why did the rescue path also fail?
The pipeline has a frontier fallback for days the local writer cannot deliver. It tries one hosted CLI engine first, then a second. On this day both were dead.
The first engine had hit its usage quota and was locked out for two more days. The second had an expired OAuth session that could not refresh. Neither failure had anything to do with the blog. Both had been true for hours before the pipeline needed them, and nothing checked. That left 2 rescue engines down at the exact moment the local model came up short.
So the day's arithmetic: one blocked cold load, one rejected draft, 2 dead rescue engines, 0 posts shipped, 0 bad posts shipped. The alert fired to my phone, and one login fixed the auth half.
What should a local writer gate check?
Deterministic things only. Do not ask a model whether a model's output is fine. My gate checks four things:
- Word count inside a configured window (550 to 1100 for blog drafts)
- Every required heading present as an exact string
- The image path matches the post slug
- No words from a parsed forbidden-word list
Each check is a string or integer comparison. Each failure names itself: the log line for this incident read "body word count 535 outside 550-1100". No detective work, no judgment call. This is the same principle as the speed and quality gate I put on benchmark runs: the model produces, the script decides.
How do you keep the rescue path alive?
The gate did its job. The gap was upstream. Engine health is pipeline health, and I only measured it at publish time.
Quota exhaustion and auth expiry are ordinary states, not incidents. Treat them like disk space. Probe every engine once a day with a one-token call and alert the moment one dies, hours before you need it. A dead fallback discovered at publish time is not a fallback.
This is also half the case for owning the hardware. The 5090 never expires a session and never hits a vendor quota. But the local box has its own guards, like the 16 GiB RAM floor, so the frontier fallback still earns its place. Watch both sides, and make the watcher deterministic.
Accompanying prompt
What the prompt does: It adds a deterministic output gate to any local LLM writer pipeline.
Copy/paste this prompt:
Copy-ready prompt
Paste the exact block into your coding agent.
No article chrome, no footnotes, no formatting drift.
This prompt and every other one we publish live in the free prompt library.
Copy the block above.
Get the artifact-backed local AI lab notes by email: https://bmdpat.com/5090-reports
FAQ
What failed in the local writer run?
The 07:45 run skipped on the 16 GiB host RAM guard. The 10:00 run generated, then the output gate counted 535 words against a 550 to 1100 window and failed a literal-string check for the closing prompt section.
Why did the rescue path also fail?
The first hosted engine had hit its usage quota and was locked out for two more days. The second had an expired OAuth session that could not refresh. Nothing checked those states before publish time.
What should a local writer gate check?
Word count inside a configured window (550 to 1100 for blog drafts), every required heading present as an exact string, the image path matches the post slug, and no words from a parsed forbidden-word list. Each check is a string or integer comparison.
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 firstGet 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.
Patrick Hughes
I build BMD and publish measured AI runs, failure reports, and reusable checks. Nashville, Tennessee.
More writing
- 5 min
Unload Local LLMs After Every Test
A local model test is not over when text appears. I unload the model, read idle VRAM, and record the result before I start another run.
- 5 min
Log Local LLM Fallbacks Before You Score the Output
My local writer hit a host RAM guard, then Sonnet produced a draft that failed QA. Here is how I separate availability, model identity, and useful output.
- 5 min
My local daily brief used 0 model calls
On September 4, 2026 my llama3.1:8b daily brief was ready with 0 model calls and 0 seconds. Preview-only file ranking is not a model run.
- 5 min
Long Context Cost Me VRAM, Not Tokens a Second
A 94x bigger prompt cost llama3.1:8b only 9.7% of its generation rate. VRAM rose 656 MiB, but num_ctx doubled in the same step. Budget memory first.
- 5 min
One model logged 14.5 and 6,178 prompt tokens a second
gemma4:26b read 53 prompt tokens at 14.5 tok/s and 4,470 at 6,178.9 on the same RTX 5090 run set. Prompt speed is not one number.