{"record":{"id":"7bd92b465d038a4e","repo":"n8n-io/n8n","slug":"keys-and-values-must-be-arrays","errorCode":null,"errorMessage":"keys and values must be arrays","messagePattern":"keys and values must be arrays","errorType":"exception","errorClass":"ExpressionExtensionError","httpStatus":null,"severity":"error","filePath":"packages/@n8n/expression-runtime/src/extensions/function-extensions.ts","lineNumber":25,"sourceCode":"const numberList = (start: number, end: number): number[] => {\n\tconst size = Math.abs(start - end) + 1;\n\tconst arr = new Array<number>(size);\n\n\tlet curr = start;\n\tfor (let i = 0; i < size; i++) {\n\t\tif (start < end) {\n\t\t\tarr[i] = curr++;\n\t\t} else {\n\t\t\tarr[i] = curr--;\n\t\t}\n\t}\n\n\treturn arr;\n};\n\nconst zip = (keys: unknown[], values: unknown[]): unknown => {\n\tif (!Array.isArray(keys) || !Array.isArray(values)) {\n\t\tthrow new ExpressionExtensionError('keys and values must be arrays');\n\t}\n\tif (keys.length !== values.length) {\n\t\tthrow new ExpressionExtensionError('keys and values not of equal length');\n\t}\n\tconst result: Record<string, unknown> = {};\n\tfor (let i = 0; i < keys.length; i++) {\n\t\tresult[keys[i] as string] = values[i];\n\t}\n\treturn result;\n};\n\nconst average = (...args: number[]) => {\n\treturn aAverage(args);\n};\n\nconst not = (value: unknown): boolean => {\n\treturn !value;\n};","sourceCodeStart":7,"sourceCodeEnd":43,"githubUrl":"https://github.com/n8n-io/n8n/blob/5ac6606e81f67bb9534255570cd4e86fd8101eee/packages/@n8n/expression-runtime/src/extensions/function-extensions.ts#L7-L43","documentation":"The `zip(keys, values)` function-extensions helper builds an object from two parallel arrays. It throws `ExpressionExtensionError` when either argument fails `Array.isArray(...)`, because the subsequent loop indexes into them positionally.","triggerScenarios":"Passing a non-array argument: `{{ zip($json.headers, $json.row) }}` where `row` is an object or string; `{{ zip('a,b', [1,2]) }}`.","commonSituations":"Upstream field is a string or object instead of an array; passing a single value where a list was expected.","solutions":["Ensure both arguments are arrays — wrap with `[...]` or `Array.from(...)` in a Code node if needed.","If the source is a delimited string, `.split(',')` it first.","Confirm both upstream fields are typed as arrays before the expression runs."],"exampleFix":"// before\n{{ zip($json.headers, $json.rowObject) }}\n// after\n{{ zip($json.headers, $json.rowArray) }}","handlingStrategy":"validation","validationCode":"const { keys, values } = $json;\nif (!Array.isArray(keys) || !Array.isArray(values)) {\n  throw new Error('zip(): keys and values must both be arrays');\n}\nreturn $json;","typeGuard":"const areBothArrays = (a: unknown, b: unknown): a is unknown[] & unknown[] =>\n  Array.isArray(a) && Array.isArray(b);","tryCatchPattern":null,"preventionTips":["Ensure both arguments are arrays before calling `zip`.","Split delimited strings with `.split(',')` first.","Coerce objects to entry arrays in a Code node when needed."],"tags":["expression","array","argument-shape","validation"],"backgroundTag":null,"analyzedSha":"5ac6606e81f67bb9534255570cd4e86fd8101eee","analyzedAt":"2026-08-12T05:26:35.080Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}