PairedItem in n8n: understanding and fixing data linking errors
Published 31 July 2026 · 6 min read
A workflow runs perfectly in testing, node by node. Then you add a Merge, an Aggregate, or a Code node that rolls up several rows into one — and an expression further down, one that worked fine yesterday, starts throwing Paired item data for item from node [name] is unavailable or, on older instances, Referenced node is not part of input. The data is right there, visible in the offending node's output panel. The problem isn't the data itself — it's the invisible thread meant to link it back to its source, and that thread just snapped.
What n8n actually means by pairedItem
Every item flowing between two n8n nodes carries two things: its content (json) and an invisible piece of metadata, pairedItem, pointing to the item (or items) in the previous node it directly came from. That chain, link by link back to the trigger, is what lets an expression like {{ $('Classify email').item.json.category }} find the right value even three nodes downstream, without you having to manually re-copy that information at every step.
This mechanism isn't an n8n quirk — it mirrors a well-studied problem in computing: data provenance in pipeline-style processing systems, the ability to trace a given result back to exactly which source data it came from. A landmark study by Simmhan, Plale, and Gannon, published in 2005 in ACM SIGMOD Record, surveys these provenance systems in distributed scientific workflows and notes that this automatic traceability is both a central feature and a recurring point of fragility the moment data flows stop being strictly linear (Simmhan, Plale & Gannon, 2005, ACM SIGMOD Record). A broken pairedItem in n8n is exactly that same lineage break, at the scale of an automation workflow rather than a distributed scientific computation.
As long as a workflow stays strictly linear — one item in, one item out, at every node — this chain builds itself and stays invisible. The problem starts the moment a node breaks the one-to-one correspondence between its input and its output.
The two error messages that signal the same problem
Depending on the n8n version and exactly where the reference breaks, two different wordings show up for the same underlying cause:
- Paired item data for item from node [X] is unavailable. Ensure [X] is providing the required output. — the current, most common message: n8n knows it needs to trace a link back to node X, but finds no usable
pairedItemin the items that node produced. - Referenced node is not part of input — an older wording, seen on earlier versions or in certain expression contexts, for the same failure to trace lineage back to the target node.
Either way, the fix is the same: restore the pairedItem chain at the source, or change how you reference the node downstream.
Why the chain breaks
Three situations account for most real-world cases:
A Code node that aggregates several items into one. A Code node in Run Once for All Items mode that computes a total, an average, or a summary from ten input items and returns only a single output item can't, by default, know which of the ten input items to attribute that single result to. Without your intervention, n8n doesn't guess that link — the node has to state it itself.
A Merge node in Combine mode with misaligned branches. As covered in our Merge node guide, Position and Matching Fields modes pair up items from two different inputs. The moment one branch has lost items along the way (an upstream IF or Filter), the pairing can become ambiguous, and the merged item's original lineage is no longer a single, obvious path.
A Code node that rebuilds items without carrying pairedItem forward. This is the most common cause. The moment a Code node sorts, filters, or rebuilds its output array instead of transforming items one by one in order, the output index no longer mechanically matches the input index — and without pairedItem explicitly set, n8n loses the thread.
Fixing it in the Code node
Our Code node guide covers the general items format; here's precisely where to place pairedItem. For a one-to-one transformation that reorders or filters items:
const input = $input.all();
return input
.filter(item => item.json.status === "valid")
.map(item => ({
json: { ...item.json, processed: true },
pairedItem: { item: input.indexOf(item) }
}));
For an aggregation that condenses several items into a single result, pairedItem becomes an array rather than a single object — you list every input item that contributed to the result:
const input = $input.all();
const total = input.reduce((sum, item) => sum + item.json.amount, 0);
return [{
json: { total },
pairedItem: input.map((_, index) => ({ item: index }))
}];
This second form restores a valid lineage even when the relationship is no longer one-to-one: n8n then knows that this single result depends on the entire set of input items, and any downstream expression trying to trace back to them works again.
Working around it without fixing the chain
Fixing pairedItem at the source is the cleanest solution, but it assumes you have control over the offending Code node — not always the case after a core node like Aggregate, Summarize, or a LangChain Information Extractor, for instance. The fallback is to change how you access the source node in the failing expression:
$('Node name').first()— the first item produced by that node, regardless of the current item's position.$('Node name').last()— the last one.$('Node name').all()[2]— a specific index, when you know exactly where the data you need sits.
These three forms deliberately bypass automatic lineage: they work by position rather than actual ancestry. That's perfectly fine when the source node only ever produces one relevant item (a total, a config value), but risky if several different items can end up there depending on the run — you'd then silently get the wrong value instead of a visible error.
A practical case: recovering the document ID after a RAG Aggregate
A typical document ingestion pipeline — like the one detailed in our RAG chunking guide — splits a PDF into dozens of chunks, computes an embedding for each, then groups them with an Aggregate node before a batched Supabase insert. If a node downstream of that Aggregate needs to recover the original document ID via $('Read PDF').item, the error shows up almost every time: the Aggregate produced a single item from dozens, and lineage back to one specific source item no longer has a unique, well-defined meaning.
The right fix here isn't to repair the Aggregate's pairedItem — it's to avoid needing it at all: include the document ID directly in each chunk's json from the node that creates them, rather than fetching it later via lineage. The data then travels with the item itself — carrying the information you need along with the item is almost always the more robust approach, rather than relying on lineage to recover it after the fact.
Common pitfalls
- Treating the error as an n8n bug: it's an accurate signal — the lineage really is ambiguous, and guessing on your behalf would produce a wrong result rather than a visible error.
- Reaching for
.first()everywhere out of habit: this hides the error without guaranteeing the retrieved value is the right one once the source node produces several distinct items. - Forgetting to set
pairedItemafter sorting or filtering in a Code node, when the item count genuinely changes between input and output. - Not carrying the needed information in the item's
json, and relying on lineage to recover it three nodes later — fragile the moment a Merge or Aggregate sits in between.
Going further
This kind of linking break typically shows up in pipelines that combine multiple branches or group batches of items — exactly the cases covered by the ingestion workflows in the RAG Assistant Pack (€119), already built to carry the identifiers they need without depending on fragile lineage after an Aggregate. If you're writing your own Code nodes, our Merge node guide and our Split Out and Aggregate guide cover the two other core nodes that most often break this chain — enough to spot the problem before it hits production.
FAQ
Frequently asked questions
Does pairedItem do anything beyond triggering error messages?
Yes, that's actually its primary job: it powers the data mapping panel (the lines that visually connect a field to its source) and lets expressions like $('Node name').item find the originating item without you having to manually carry an identifier through the entire workflow. The error only shows up once that chain breaks somewhere upstream.
Do I need to set pairedItem on every Code node I write?
No. As long as a Code node returns exactly one output item per input item, in the same order, n8n infers the link correctly on its own. Manual handling only becomes necessary once the item count changes between input and output, or the order is altered (sorting, filtering, grouping).
Why not just use $input.first() everywhere to sidestep the problem?
Because $input.first() always returns the item at position zero of the referenced node, regardless of which item is currently being processed downstream. That works by coincidence when there's only one item, but returns the wrong value the moment the upstream node produced several different items depending on the branch taken. Use it deliberately, not as a blanket workaround.
Does this error also show up with AI (LangChain) nodes?
Yes, particularly after an Information Extractor, a Text Classifier, or an LLM chain running in Run Once for All Items mode that summarizes several items into a single structured output. The fix follows the same logic: either set pairedItem explicitly on the output, or reference the source node with .first(), .last(), or an index instead of .item.
Bundle FlowKit Complet
€269