n8n logon8n Automation Hub
Debugging notes

I Wired Four Nodes Into One and It Ran Four Times Instead of Once

Debugging notes · n8n workflow · September 1, 2026

The workflow had worked fine with three parallel API calls feeding one report node for weeks. Adding a fourth branch looked like the same pattern, one more time. It wasn't — and the failure mode wasn't an error message, it was four of everything.

Workflow at a glance
  1. A daily monetization-tracker workflow pulled stats from 3 YouTube channels in parallel, all reading into one "Build Report" node via expressions like $('Get FA Channel Stats').first().json
  2. Adding a 4th channel exposed the first bug: "Build Report" was only directly *connected* from one of the three stat nodes, so it sometimes ran before the new branch's slower HTTP call had finished — Node 'Get News Channel Stats' hasn't been executed
  3. The obvious-looking fix: wire all 4 stat nodes directly into "Build Report" so n8n waits for every branch before running it
  4. That "fix" caused a worse bug: connecting multiple nodes to the same input does not make the target wait — it re-triggers the target once per incoming connection
  5. Result on the very next manual run: "Build Report" executed 4 times in one workflow run, sending 4 duplicate Telegram messages and writing 4×4 = 16 duplicate rows to the tracking Sheet
  6. Real fix: a dedicated Merge node (mode: append, one input per branch) between the stat nodes and "Build Report" — Merge node inputs genuinely wait for all of them, plain multiple connections into the same node input do not
Diagram of the monetization tracker workflow: Schedule Trigger fanning out into six parallel YouTube-stats HTTP nodes, all merging through a Merge Stats node before Build Report, Is Row, and the Sheets/Telegram outputs

Node diagram reconstructed from the live workflow via the n8n API — the Merge Stats node is the fix described below.

A working 3-branch report, and a 4th branch that looked identical

The workflow was simple on purpose: a Schedule Trigger fires daily, three parallel HTTP Request nodes each pull one YouTube channel's stats, and a single Code node ("Build Report") reads all three results and builds one Telegram summary plus one spreadsheet row. It had run cleanly every day for weeks. Adding a fourth tracked channel meant adding a fourth HTTP Request node — the same shape as the other three, doing the same job, reading the same API.

Bug one: "Build Report" was never actually waiting on all of them

"Build Report" had only ever been wired with a direct connection from one specific stat node — the other two were read purely through $('NodeName').first().json expressions, which only work correctly if that node has already executed by the time the expression runs. With three same-speed API calls, this was never visible: they finished close enough together that the one connected node was reliably the slowest of the three by the time it mattered. The fourth channel's HTTP call ran at a different, independent speed, and one of the original three branches (an OAuth error, returning fast with a failure rather than a slow success) now sometimes returned before the new channel's call had, tripping the whole thing over into an execution-order dependency that had been silently assumed correct for weeks.

The error was blunt: Node 'Get News Channel Stats' hasn't been executed. The fix looked equally blunt — connect every stat node directly into "Build Report," so the node's own multiple-input wiring, not an expression's silent assumption, decides when it's safe to run.

Bug two: connecting four nodes to one input doesn't mean "wait for four"

That fix shipped, and the very next manual re-run made it obvious it was wrong in a completely different way: "Build Report" ran four times in a single workflow execution — once immediately after each of its four predecessors finished, independently. Four Telegram messages landed in the same chat within seconds of each other. The tracking Sheet, which appends one row per "Build Report" run, got 16 new rows instead of 4 — each of the 4 executions itself read all 4 stat nodes' current data, so every duplicate execution wrote 4 near-identical rows.

The mental model that failed: connecting several nodes to the same input on this n8n version does not create a fan-in that waits for all of them, the way it might in a diagram on a whiteboard. Each incoming connection independently re-triggers the receiving node whenever that specific predecessor finishes. Four wires in meant four separate re-runs, not one merged run.

The actual fix: a Merge node, not more direct connections

The genuine fan-in primitive is a dedicated Merge node (mode: "append", numberInputs set to the branch count — 4 at the time, since grown to 6 as more channels were added). Each stat node was rewired into its own numbered input slot on the Merge node instead of directly into "Build Report"; the Merge node's single output then feeds "Build Report." Unlike plain multiple connections into one node, a Merge node's inputs genuinely do wait for every configured input to arrive before it emits anything downstream — this is the behavior the original wiring was mistakenly assumed to already have.

Cleaning up what the bug already wrote

By the time the fix shipped, 16 duplicate rows were already sitting in the tracker Sheet from the bad run. A disposable webhook-triggered n8n workflow (create, activate, call once, deactivate, delete — never left running) read the Sheet to identify the 16 rows by their shared timestamp, then deleted them. One more real gotcha surfaced here: the Google Sheets node's delete operation with startIndex + numberOfRows: 16 only actually deleted 1 row per call, not 16 — worked around by calling the single-row delete 16 times in a row instead (each call deletes whatever now sits at that index, since rows shift up after every delete). A fresh read afterward confirmed the Sheet was back to exactly the legitimate rows.

What actually counted as fixed

The next scheduled 08:00 CEST run was the real test: exactly one Telegram message, one row per channel written once, no duplicates. The lesson wasn't really about YouTube stats or Telegram — it's that "connect several nodes into one" and "wait for several nodes, then run once" look identical on the canvas and are not the same wiring at all. If a node has more than one direct predecessor and the number of times it should run matters, that's a Merge node's job, not a coincidence of how fast each branch happens to finish.

Getting duplicate messages or rows out of a workflow that "looks" correctly wired?

I debug production n8n pipelines where the canvas looks right but the execution order or fan-in behavior isn't what it appears to be.