n8n logon8n Automation Hub
Incident report

A Node With No Outgoing Connections Never Ran, Even Though Another Node Referenced It by Name

Incident report · n8n workflow · September 10, 2026

A daily news-video pipeline got all the way through rendering, both short-form uploads, and its log — then crashed at the final long-form upload step with an error that a node "hasn't been executed." That node looked connected. It was a dead end that had simply never run.

Workflow at a glance
  1. A scheduled daily workflow renders a long-form news episode plus two Shorts, uploads the Shorts, then uploads the long-form video with chapter markers built by a dedicated "Build Chapters" node
  2. The upload node's description field pulled the chapter text purely by expression: {{ $('Build Chapters').first().json.chaptersText }}
  3. "Build Chapters" itself had zero outgoing connections in the graph — it sat as a parallel sibling off an earlier node, alongside a different branch that did the actual rendering work
  4. The run failed with ExpressionError: Node 'Build Chapters' hasn't been executed, confirmed absent from the execution's own list of nodes that ran
  5. Its sibling branch (the one with a real forward connection) proceeded all the way to the failing upload step, which is why every earlier stage of the run had already succeeded
  6. Fix: splice the node into the graph's actual serial path, so something genuinely depends on its output before the node that reads it via expression

A failure that showed up only at the very last step

The run had, by every visible measure, gone well: six video segments rendered, both Shorts uploaded and published, the news log appended with the day's story. The failure only appeared at the final step, uploading the long-form video to YouTube, with ExpressionError: Node 'Build Chapters' hasn't been executed. Everything before that step had worked, which made a wiring problem in an early node an unlikely first guess — the graph clearly wasn't broken in any way that would have stopped rendering.

A node that looked wired in, and wasn't

Looking at the workflow's canvas, "Build Chapters" appeared to sit reasonably inside the graph — positioned right alongside the node that builds the render's concat list, visually part of the same cluster of nodes. What the canvas view didn't make obvious at a glance: it had zero outgoing connections. It was wired as a sibling off "Build Concat List," parallel to a second sibling, "SSH - Write Concat List," which is the branch that actually continues into the real render pipeline. "Build Chapters" itself just stopped there — nothing downstream ever consumed its output through an actual connection.

The upload node only reached it through an expression, not a wire

The long-form upload node's description field was built from {{ $('Build Chapters').first().json.chaptersText }} — a cross-reference expression that pulls a named node's output directly, regardless of whether that node sits anywhere on the actual path leading to the node using it. That kind of reference reads, at first glance, like it guarantees the referenced node has run: it names the node explicitly, after all. It doesn't. n8n executes nodes by following real graph connections forward from the trigger; a node with no outgoing connection of its own is never scheduled to run at all, no matter how many other nodes plan to read from it by name later.

Why it worked, seemingly, before this run

Confirming this specific run's execution list against the full set of nodes that actually fired showed "Build Chapters" genuinely absent — not merely producing empty output, but never executed at all. Its sibling branch, "SSH - Write Concat List," happened to run because it does have a real forward connection continuing the render, so every stage that branch feeds into (a multi-minute ffmpeg render, download, upload) proceeded normally, right up to the one place that expected the parallel dead-end's output.

The fix, and the lesson underneath it

The fix itself was straightforward once the actual problem was clear: rewire "Build Chapters" into the real serial path — from the ffmpeg concat step, through "Build Chapters," into the download step that precedes the upload — instead of leaving it as a disconnected leaf off an earlier node. The broader lesson is the part worth carrying into any other workflow: a node referenced only through a $('NodeName') expression, with no real outgoing connection of its own, is not guaranteed to execute just because the graph shows it positioned as a sibling of a node that does run. If something depends on a node's output, that dependency needs to exist as an actual connection somewhere in the graph — not only as an expression reference that assumes the node ran.

Recovering the run that had already partly succeeded

Because the Shorts uploads and the sheet log had already gone out for real by the time the failure hit, simply re-triggering the whole workflow risked duplicating that already-completed work. The safer path: confirm the rendered long-form file still existed on disk, pull the real title, description, tags, and chapter data straight from the failed execution's own captured node output, and run a one-off recovery workflow that repeated only the missing steps — download, upload, thumbnail, notification — rather than the entire pipeline from the start.

A workflow failing at the last step after everything else worked?

I debug production n8n workflows for a living, including graph-wiring bugs that only surface on the one execution where a parallel branch's timing finally matters.