The named key isn't one of n8n's five reserved item keys, and this item has no reserved key of its own — but some other item in the array you returned does.
That last clause is the whole diagnosis, and it isn't in the message: this error means your array is inconsistent. Some items are correctly-formed n8n items and this one is a bare object. n8n's description tells you the fix without telling you the cause:
Access the properties of an item under
.json, e.g.item.json
Both come out of the same check, three lines apart, and the difference is precise:
| This item has… | You get |
|---|---|
| a reserved key and a foreign key | Invalid output format |
| a foreign key and no reserved key | Unknown top-level item key: <key> |
And the check only runs at all when at least one item somewhere in the array carries
a reserved key. If no item does, n8n wraps every object in json for you and nothing is
validated — which is why a uniformly bare array like return [{ a: 1 }, { a: 2 }] works
perfectly.
So the shape that produces this error looks like this:
return $input.all().map(item => {
if (item.json.skip) {
return { json: { skipped: true } }; // an n8n item
}
return { name: item.json.name }; // NOT an n8n item
});
Both halves look reasonable in isolation. Together they're a mixed array, and the first branch is what switches validation on for the second.
Make every item the same shape. Pick the envelope and use it everywhere:
return $input.all().map(item => {
if (item.json.skip) {
return { json: { skipped: true } };
}
return { json: { name: item.json.name } };
});
If the inconsistency is coming from a .filter() or an early return inside a loop,
the usual culprit is one path that forgot the wrapper. Search your function for every
return and push and check they all produce the same keys.
This is worth knowing because it rules out half the places you might look.
In Run Once for Each Item mode you return a single object, and n8n normalises it
before validating: a bare object gets wrapped in json first, so there's nothing
foreign left at the top level by the time the check runs. The only way to fail in that
mode is to hand over an object that already has json plus something else — and that
produces Invalid output format, not this.
So if you're reading this message, you are in Run Once for All Items mode, and the problem is across your items rather than inside any one of them.
There's a narrow path where a mixed array slips past this check and fails one step later, inside n8n's normalisation helper, with:
Inconsistent item format
It happens when the non-json items carry only reserved keys — say
[{ json: {…} }, { pairedItem: 0 }]. Nothing foreign is present, so the check above has
nothing to complain about, and the normaliser refuses the mix instead. Same underlying
mistake, different message, and the fix is identical: one shape for every item.
n8n can't require the json envelope outright, because returning bare objects is a
documented convenience and a lot of working code depends on it. So the envelope is
optional — until you use it. The moment one item declares itself an n8n item, n8n stops
guessing for the rest of the batch and starts enforcing.
That conditional behaviour is the reason this error can appear in a workflow that ran
fine yesterday: add one branch that returns { json: … }, and every other branch is
suddenly being held to a standard it wasn't before.
Source: validateTopLevelKeys in
packages/nodes-base/nodes/Code/result-validation.ts, and
packages/core/src/execution-engine/node-execution-context/utils/normalize-items.ts
for the normalisation order and the Inconsistent item format path. Read directly from
n8n's repository; the Code node documentation does not list these error strings.
Last verified 16 September 2026 against n8n 2.39.5 (source read on master @ 2.40.0). n8n changes these messages between releases; if the wording you see differs, the version above is what this page was checked against.