n8nollamaautomationlocal-llm

2026-10-19 20:00 UTC

An orchestration node aborted after exactly 300 seconds — and it wasn't the timeout at all

Problem

A self-hosted n8n workflow that fan-outs to a local Ollama model kept failing. The step that asks the model to write content — an HTTP node pointed at a small local service that wraps Ollama — died after precisely 300078 ms with The connection was aborted, perhaps the server is offline. Every upstream node succeeded; only the LLM step failed, and always at almost exactly 300 s. A five-minute wall clock looked like a timeout — so the first instinct was "raise the timeout." That instinct was wrong.

Investigation

The same HTTP call, run by hand from the host, returned in 24 s. So the service was healthy; the request path inside the workflow was not. Two measured facts broke the case open:

  • The service logged dozens of requests arriving within the same second — far more than the handful of items being processed.
  • Those requests did not fail fast. Their service-side durations climbed across the batch: 47 s, 74 s, 102 s, … 288 s. That is the unmistakable signature of queueing, not of a slow individual call.

Two separate faults were stacking:

1. A generation cap that was far too generous. The wrapper passed num_predict: 8192 to the model. On a long prompt the 30B model would ramble for ~272 s on a single call. Capping generation at 3072 brought the same call down to ~24 s — a 10× win with no meaningful quality loss for the task. (A short prompt had masked this: a quick test had completed in ~36 s, which made the long path look fine.)

2. An unbounded parallel fan-out onto a single-threaded backend. This was the real killer. The workflow's trigger carried a configuration parameter (a "dry-run" flag) that was meant to shrink the batch. But a trigger's parameters are node metadata, not item data — they never appear in $json. So the downstream expression $json.dry_run evaluated to undefined, the batch size silently fell back to its default of 50, and the workflow fanned all ~46 results into the LLM step at once. Ollama serializes generation; 46 concurrent requests became a queue whose tail exceeded the node's 300 s limit. The node that "timed out" was simply the last in line.

Fix

Cap generation and bound the batch:

# wrapper: make the generation cap a knob, default it sanely
num_predict: Number(process.env.NUM_PREDICT || 3072)
# workflow: hard-code a small batch for the manual/triggered path;
# trigger parameters are NOT item data, so $json.dry_run never resolves
limit: 2

Then the workflow was re-run untouched, end to end.

Verification

  • The generation step dropped to ~70 s for a real item; the whole 7-node run finished green in ~80 s, every node success.
  • The service log confirmed the downstream render steps returned 200 in under a second each — the queue was gone.

Lesson

When a failure lands on a suspiciously round number like 300 s, resist "raise the timeout." A wall-clock value that matches a configured limit exactly is a hint, not a cause. Look for the queue: many near-simultaneous requests with climbing durations mean a slow backend serializing a fan-out, and the timeout is merely where the line snapped. And remember that a trigger node's parameters are not delivered to the workflow as item data — an expression that reads a config value off the trigger will silently resolve to undefined and fall through to a default. Bound the fan-out, cap the generation, and re-measure before touching the timeout.