n8n-io/n8n · error · ExpressionExtensionError
merge(): expected array arg, e.g. .merge([{ id: 1, otherValu
Error message
merge(): expected array arg, e.g. .merge([{ id: 1, otherValue: 3 }]) What it means
Thrown as ExpressionExtensionError by the .merge() array extension when its argument is present but not an array. merge() merges two object-arrays element-by-element; if called with no argument it instead merges all objects within the array itself. A present-but-non-array argument (e.g. a single object) is invalid because merge iterates by index against the base array.
Source
Thrown at packages/@n8n/expression-runtime/src/extensions/array-extensions.ts:250
return newObject;
}
function merge(value: unknown[], extraArgs: unknown[][]): unknown {
const [others] = extraArgs;
if (others === undefined) {
// If there are no arguments passed, merge all objects within the array
const merged = value.reduce((combined, current) => {
if (current !== null && typeof current === 'object' && !Array.isArray(current)) {
combined = mergeObjects(combined as Record<string, unknown>, [current]);
}
return combined;
}, {});
return merged;
}
if (!Array.isArray(others)) {
throw new ExpressionExtensionError(
'merge(): expected array arg, e.g. .merge([{ id: 1, otherValue: 3 }])',
);
}
const listLength = value.length > others.length ? value.length : others.length;
let merged = {};
for (let i = 0; i < listLength; i++) {
if (value[i] !== undefined) {
if (typeof value[i] === 'object' && typeof others[i] === 'object') {
merged = Object.assign(
merged,
mergeObjects(value[i] as Record<string, unknown>, [others[i]]),
);
}
}
}
return merged;
}
View on GitHub (pinned to 5ac6606e81)
Solutions
- Wrap the argument in an array: .merge([{id:1, otherValue:3}]).
- If you want to merge all objects within the array itself, call .merge() with NO argument.
- Guard with Array.isArray(arg) before calling.
- Match the documented shape exactly: base array + array argument.
Example fix
// before — single object argument
{{ $json.rows.merge({ id: 1, otherValue: 3 }) }}
// after — array argument
{{ $json.rows.merge([{ id: 1, otherValue: 3 }]) }} Defensive patterns
Strategy: type-guard
Validate before calling
function mergeSafe(arr, others) {
if (others !== undefined && !Array.isArray(others)) throw new TypeError('merge(): expected array arg');
// ...proceed with arr.merge(others)
} Type guard
function isMergeArgValid(others) { return others === undefined || Array.isArray(others); } Try / catch
try {
result = arr.merge(others);
} catch (e) {
if (e.name === 'ExpressionExtensionError' && /merge.*array/i.test(e.message)) {
// wrap the argument in an array: arr.merge([others])
}
} Prevention
- Wrap merge arguments in an array: .merge([{id:1,otherValue:3}]).
- Call .merge() with no argument to merge all objects within the array itself.
- Guard with Array.isArray(arg) before calling.
- Match the documented shape exactly.
When it happens
Trigger: Calling .merge() with a single object instead of an array of objects: [...].merge({id:1}) instead of [...].merge([{id:1}]). The check `if (!Array.isArray(others))` catches primitives, plain objects, strings, etc.
Common situations: Passing a bare object literal when the API expects an array of objects. A template variable that resolves to an object rather than an array. Misreading the doc example and dropping the enclosing brackets.
Related errors
- merge(): expected object arg
- arguments must be passed to pluck
- smartJoin(): expected two string args, e.g. .smartJoin("name
- chunk(): expected non-zero numeric arg, e.g. .chunk(5)
- renameKeys(): expected an even amount of args: from1, to1 [,
AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12).
Data as JSON: /api/errors/141ced5433c72bb5.
Report an issue: GitHub.