{"id":"483b86f48e5c366e","repo":"jestjs/jest","slug":"each-must-be-called-with-an-array-or-tagged-tem","errorCode":null,"errorMessage":"`.each` must be called with an Array or Tagged Template Literal.\n\nInstead was called with: ${pretty(table, {maxDepth: 1, min: true})}\n","messagePattern":"`\\.each` must be called with an Array or Tagged Template Literal\\.\n\nInstead was called with: (.+?)\\)\\}\n","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/jest-each/src/validation.ts","lineNumber":20,"sourceCode":" * Copyright (c) Meta Platforms, Inc. and affiliates.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n\nimport chalk from 'chalk';\nimport type {Global} from '@jest/types';\nimport {format as pretty} from 'pretty-format';\n\ntype TemplateData = Global.TemplateData;\n\nconst EXPECTED_COLOR = chalk.green;\nconst RECEIVED_COLOR = chalk.red;\n\nexport const validateArrayTable = (table: unknown): void => {\n  if (!Array.isArray(table)) {\n    throw new TypeError(\n      '`.each` must be called with an Array or Tagged Template Literal.\\n\\n' +\n        `Instead was called with: ${pretty(table, {\n          maxDepth: 1,\n          min: true,\n        })}\\n`,\n    );\n  }\n\n  if (isTaggedTemplateLiteral(table)) {\n    if (isEmptyString(table[0])) {\n      throw new Error(\n        'Error: `.each` called with an empty Tagged Template Literal of table data.\\n',\n      );\n    }\n\n    throw new Error(\n      'Error: `.each` called with a Tagged Template Literal with no data, remember to interpolate with ${expression} syntax.\\n',\n    );","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/jest-each/src/validation.ts#L2-L38","documentation":"validateArrayTable runs deeper validation on the array path of jest-each. The first guard re-checks that the supplied table is actually an Array; if it is not, it reports the offending value (pretty-formatted at maxDepth 1) so the user can see exactly what was passed. This is a stricter, more informative sibling of the index.ts check.","triggerScenarios":"Reaching bind's array branch with a non-array — typically by manually constructing a table variable that was expected to be an array but resolved to undefined/null/object, or by spreading incorrectly so the table slot receives a non-array.","commonSituations":"A helper returns `undefined` on an edge case and you pass it straight to `.each`; an async/await omission means a Promise is passed instead of the resolved array; default-export interop returns the module namespace object instead of the array.","solutions":["Inspect the `Instead was called with:` line to see the actual value, then fix its source.","Guard the helper: `const table = await getRows(); if (!Array.isArray(table)) throw ...`.","If the value is a Promise, add `await` before passing it.","If it is an array-like, convert with `Array.from(...)`."],"exampleFix":"// before\nconst rows = fetchRows(); // returns a Promise\nit.each(rows)('row %j', (r) => {});\n\n// after\nconst rows = await fetchRows();\nit.each(rows)('row %j', (r) => {});","handlingStrategy":"validation","validationCode":"const table = await getRows();\nif (!Array.isArray(table)) {\n  throw new TypeError(`each() expected array, got ${typeof table}`);\n}\nit.each(table)(...);","typeGuard":"const isRowArray = (t: unknown): t is unknown[] => Array.isArray(t);","tryCatchPattern":null,"preventionTips":["Always await data sources before passing to .each.","Log array length in dev to catch empty/non-array early.","Validate helper return types with TypeScript."],"tags":["jest-each","parameterized-tests","validation","async"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}