jestjs/jest · error · TypeError
`.each` must be called with an Array or Tagged Template Lite
Error message
`.each` must be called with an Array or Tagged Template Literal.
Instead was called with: ${pretty(table, {maxDepth: 1, min: true})}
What it means
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.
Source
Thrown at packages/jest-each/src/validation.ts:20
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
*/
import chalk from 'chalk';
import type {Global} from '@jest/types';
import {format as pretty} from 'pretty-format';
type TemplateData = Global.TemplateData;
const EXPECTED_COLOR = chalk.green;
const RECEIVED_COLOR = chalk.red;
export const validateArrayTable = (table: unknown): void => {
if (!Array.isArray(table)) {
throw new TypeError(
'`.each` must be called with an Array or Tagged Template Literal.\n\n' +
`Instead was called with: ${pretty(table, {
maxDepth: 1,
min: true,
})}\n`,
);
}
if (isTaggedTemplateLiteral(table)) {
if (isEmptyString(table[0])) {
throw new Error(
'Error: `.each` called with an empty Tagged Template Literal of table data.\n',
);
}
throw new Error(
'Error: `.each` called with a Tagged Template Literal with no data, remember to interpolate with ${expression} syntax.\n',
);View on GitHub (pinned to f49721c78e)
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(...)`.
Example fix
// before
const rows = fetchRows(); // returns a Promise
it.each(rows)('row %j', (r) => {});
// after
const rows = await fetchRows();
it.each(rows)('row %j', (r) => {}); Defensive patterns
Strategy: validation
Validate before calling
const table = await getRows();
if (!Array.isArray(table)) {
throw new TypeError(`each() expected array, got ${typeof table}`);
}
it.each(table)(...); Type guard
const isRowArray = (t: unknown): t is unknown[] => Array.isArray(t);
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- `.each` must only be called with an Array or Tagged Template
- Error: `.each` called with an empty Tagged Template Literal
- Error: `.each` called with a Tagged Template Literal with no
- Error: `.each` called with an empty Array of table data.
- Not enough arguments supplied for given headings: ${EXPECTED
AI-assisted analysis of jestjs/jest@f49721c78e (2026-08-03).
Data as JSON: /data/errors/483b86f48e5c366e.json.
Report an issue: GitHub.