{"id":"c3da7288856800a0","repo":"jestjs/jest","slug":"table-headings-do-not-conform-to-expected-format","errorCode":null,"errorMessage":"Table headings do not conform to expected format:\n\n${EXPECTED_COLOR('heading1 | headingN')}\n\nReceived:\n\n${RECEIVED_COLOR(pretty(heads))}","messagePattern":"Table headings do not conform to expected format:\n\n(.+?)\n\nReceived:\n\n(.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/jest-each/src/validation.ts","lineNumber":90,"sourceCode":"};\n\nconst pluralize = (word: string, count: number) =>\n  word + (count === 1 ? '' : 's');\n\nconst START_OF_LINE = '^';\nconst NEWLINE = '\\\\n';\nconst HEADING = '\\\\s*[^\\\\s]+\\\\s*';\nconst PIPE = '\\\\|';\nconst REPEATABLE_HEADING = `(${PIPE}${HEADING})*`;\nconst HEADINGS_FORMAT = new RegExp(\n  START_OF_LINE + NEWLINE + HEADING + REPEATABLE_HEADING + NEWLINE,\n  'g',\n);\n\nexport const extractValidTemplateHeadings = (headings: string): string => {\n  const matches = headings.match(HEADINGS_FORMAT);\n  if (matches === null) {\n    throw new Error(\n      `Table headings do not conform to expected format:\\n\\n${EXPECTED_COLOR(\n        'heading1 | headingN',\n      )}\\n\\nReceived:\\n\\n${RECEIVED_COLOR(pretty(headings))}`,\n    );\n  }\n\n  return matches[0];\n};\n","sourceCodeStart":72,"sourceCodeEnd":99,"githubUrl":"https://github.com/jestjs/jest/blob/f49721c78e195558b40913977c9230f5b7f559d8/packages/jest-each/src/validation.ts#L72-L99","documentation":"extractValidTemplateHeadings matches the header block against a strict regex `^\\n<heading>(|<heading>)*\\n` (HEADINGS_FORMAT). If the headings string does not start with a newline or does not follow the `name | name` pipe-delimited shape, no match is produced and jest-each throws with the received text at validation.ts:90.","triggerScenarios":"A tagged-template header that omits the leading newline, uses commas instead of pipes, has trailing spaces breaking the format, or contains a blank heading cell.","commonSituations":"Author writes `.each\\`a, b\\n...\\`` (comma instead of pipe); edits the template and accidentally removes the leading newline; pastes a Markdown table header expecting tab-separation; includes a column name with a space which the `\\S+`-based heading regex rejects.","solutions":["Use exactly the `heading1 | heading2` form with single-line tokens, no spaces inside tokens.","Keep the leading newline immediately after the backtick — the regex anchors on it.","Replace commas with pipes and remove spaces from column names.","If you need spaces in column names, switch to the array-of-objects form and reference fields by key."],"exampleFix":"// before\nit.each`\n  first name, last name\n  ${'Ada'} | ${'Lovelace'}\n`(...);\n\n// after\nit.each`\n  firstName | lastName\n  ${'Ada'}  | ${'Lovelace'}\n`('$firstName $lastName', ({firstName, lastName}) => {});","handlingStrategy":"validation","validationCode":"const HEADINGS = /^\\n\\s*\\S+(\\s*\\|\\s*\\S+)*\\n/;\nif (!HEADINGS.test(headerBlock)) throw new Error('invalid .each header format');","typeGuard":"const isValidHeadings = (h: string) => /^\\n\\s*\\S+(\\s*\\|\\s*\\S+)*\\n/.test(h);","tryCatchPattern":null,"preventionTips":["Use pipes and a leading newline in headers.","Avoid spaces inside column names; camelCase keys.","Switch to array-of-objects form for complex headers."],"tags":["jest-each","parameterized-tests","tagged-template","validation"],"analyzedSha":"f49721c78e195558b40913977c9230f5b7f559d8","analyzedAt":"2026-08-03T20:16:28.571Z","schemaVersion":2}