{"record":{"id":"7dfe74704980226f","repo":"heygen-com/hyperframes","slug":"missing-value-for-placeholder-key-in-row-in","errorCode":null,"errorMessage":"Missing value for placeholder {${key}} in row ${index}.","messagePattern":"Missing value for placeholder (.+?) in row (.+?)\\.","errorType":"validation","errorClass":"BatchRenderInputError","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/batchRender.ts","lineNumber":127,"sourceCode":"  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];\n  if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n    return String(value);\n  }\n\n  throw new BatchRenderInputError(\n    \"Invalid output template\",\n    `Placeholder {${key}} in row ${index} must resolve to a string, number, or boolean.`,\n  );\n}\n\nexport function resolveOutputTemplate(\n  template: string,","sourceCodeStart":109,"sourceCodeEnd":145,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/batchRender.ts#L109-L145","documentation":"BatchRenderInputError with title 'Invalid output template', thrown by placeholderValue when the output template references a {key} that is not present in the current row (Object.hasOwn(row, key) is false). The special placeholder {index} (the row's position) is always available and never triggers this error. The message names both the missing key and the row index.","triggerScenarios":"An output template like `out-{name}.mp4` where some rows omit the `name` key; a typo in the placeholder name versus the row's keys; mixed schemas across rows where only some carry the field.","commonSituations":"Template authored against one row shape but the batch contains rows with fewer keys; a key renamed in the data but not in the template; case mismatch ({Name} vs {name}).","solutions":["Make the placeholder name match a key present in every row, or add the key to the rows that lack it.","Use the always-available {index} placeholder if you only need a per-row counter.","Validate up front that every placeholder token in the template resolves against every row."],"exampleFix":"# before: template references {name}, some rows omit it\nhyperframes render --batch '[{\"out\":\"a\"}]' --output 'out-{name}.mp4'\n\n# after: use a key every row has, or {index}\nhyperframes render --batch '[{\"out\":\"a\"}]' --output 'out-{index}.mp4'","handlingStrategy":"validation","validationCode":"const PLACEHOLDER_RE = /\\{([A-Za-z0-9_.-]+)\\}/g;\nfunction assertTemplateResolves(template: string, rows: Record<string, unknown>[]) {\n  const keys = new Set<string>();\n  for (const m of template.matchAll(PLACEHOLDER_RE)) keys.add(m[1]);\n  rows.forEach((row, i) => {\n    for (const k of keys) {\n      if (k !== 'index' && !Object.hasOwn(row, k)) {\n        throw new Error(`Row ${i} missing placeholder key {${k}}`);\n      }\n    }\n  });\n}","typeGuard":null,"tryCatchPattern":"try {\n  resolveOutputTemplate(template, row, index);\n} catch (err) {\n  if (err instanceof BatchRenderInputError && err.title === 'Invalid output template') {\n    // use {index} or add the missing key to every row\n  }\n}","preventionTips":["Reuse the same key set across every row in the batch.","Use {index} when you only need a per-row counter.","Validate every placeholder against every row before rendering."],"tags":["cli","validation","batch","templating"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}