{"record":{"id":"bc9e34eee66976ec","repo":"heygen-com/hyperframes","slug":"row-index-must-be-a-json-object-of-variable-val","errorCode":null,"errorMessage":"Row ${index} must be a JSON object of variable values.","messagePattern":"Row (.+?) must be a JSON object of variable values\\.","errorType":"validation","errorClass":"BatchRenderInputError","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/batchRender.ts","lineNumber":115,"sourceCode":"}\n\nexport function parseBatchRows(raw: string, source: string): Record<string, unknown>[] {\n  const parsed = parseJson(raw, source);\n  const rows = Array.isArray(parsed) ? parsed : isRecord(parsed) ? parsed.rows : undefined;\n\n  if (!Array.isArray(rows)) {\n    throw new BatchRenderInputError(\n      \"Invalid batch payload\",\n      '--batch must be a JSON array of objects, or an object with a \"rows\" array.',\n    );\n  }\n  if (rows.length === 0) {\n    throw new BatchRenderInputError(\"Empty batch\", `${source} contains zero rows.`);\n  }\n\n  return rows.map((row, index) => {\n    if (!isRecord(row)) {\n      throw new BatchRenderInputError(\n        \"Invalid batch row\",\n        `Row ${index} must be a JSON object of variable values.`,\n      );\n    }\n    return row;\n  });\n}\n\nfunction placeholderValue(row: Record<string, unknown>, key: string, index: number): string {\n  if (key === \"index\") return String(index);\n  if (!Object.hasOwn(row, key)) {\n    throw new BatchRenderInputError(\n      \"Invalid output template\",\n      `Missing value for placeholder {${key}} in row ${index}.`,\n    );\n  }\n\n  const value = row[key];","sourceCodeStart":97,"sourceCodeEnd":133,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/batchRender.ts#L97-L133","documentation":"BatchRenderInputError with title 'Invalid batch row', thrown inside parseBatchRows' rows.map when a row is not a plain object (Record<string, unknown>). The message names the offending row index. Rows that are null, a primitive, or an array all trip this check; a row that is an object but lacks a key the output template needs trips error 98 instead.","triggerScenarios":"An array like `[\"a\", \"b\"]` (string rows), `[null]`, or `[[1,2]]` (nested arrays). Each element must itself be a JSON object.","commonSituations":"A data export that produced an array of scalars instead of objects; mixing row shapes in one batch; a templating bug that emitted the value instead of {key:value}.","solutions":["Make every element of the rows array a JSON object, e.g. `[{\"out\":\"a.mp4\"},{\"out\":\"b.mp4\"}]`.","If exporting from a spreadsheet, ensure headers map to keys (row = {column:value}).","Validate each row with a JSON-schema or type guard before writing the batch file."],"exampleFix":"# before: array of scalars\nhyperframes render --batch '[\"a.mp4\",\"b.mp4\"]'\n\n# after: array of objects\nhyperframes render --batch '[{\"out\":\"a.mp4\"},{\"out\":\"b.mp4\"}]'","handlingStrategy":"type-guard","validationCode":"function assertRowsAreObjects(rows: unknown[]) {\n  rows.forEach((r, i) => {\n    if (r === null || typeof r !== 'object' || Array.isArray(r)) {\n      throw new Error(`Row ${i} is not a JSON object`);\n    }\n  });\n}","typeGuard":"function isRecord(value: unknown): value is Record<string, unknown> {\n  return value !== null && typeof value === 'object' && !Array.isArray(value);\n}","tryCatchPattern":"try {\n  parseBatchRows(raw, source);\n} catch (err) {\n  if (err instanceof BatchRenderInputError && err.title === 'Invalid batch row') {\n    // rewrite each non-object element as { value: element }\n  }\n}","preventionTips":["Ensure the data export emits an object per row (column header -> value).","Validate each row with the isRecord type guard before writing the batch.","Watch for null or array rows that slip in from cleaning steps."],"tags":["cli","validation","batch","type-guard"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}