{"record":{"id":"57a91899d7b1b403","repo":"heygen-com/hyperframes","slug":"placeholder-key-in-row-index-must-resolve","errorCode":null,"errorMessage":"Placeholder {${key}} in row ${index} must resolve to a string, number, or boolean.","messagePattern":"Placeholder (.+?) in row (.+?) must resolve to a string, number, or boolean\\.","errorType":"validation","errorClass":"BatchRenderInputError","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/batchRender.ts","lineNumber":138,"sourceCode":"    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,\n  row: Record<string, unknown>,\n  index: number,\n): string {\n  return template.replace(PLACEHOLDER_RE, (_match, key: string) =>\n    placeholderValue(row, key, index),\n  );\n}\n\nfunction isSameOrChildPath(path: string, parent: string): boolean {\n  return path === parent || path.startsWith(parent.endsWith(sep) ? parent : parent + sep);\n}","sourceCodeStart":120,"sourceCodeEnd":156,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/batchRender.ts#L120-L156","documentation":"BatchRenderInputError with title 'Invalid output template', thrown by placeholderValue when the placeholder key exists in the row but its value is not a string, number, or boolean (e.g. it is null, an object, or an array). Only primitives can be safely coerced with String(value); structured values are rejected to avoid producing '[object Object]' or 'Array' in filenames.","triggerScenarios":"A row like `{\"user\":{\"name\":\"Ann\"}}` with template `{user}.mp4`; a row whose value is null `{\"name\":null}`; an array-valued field used as a placeholder.","commonSituations":"Nested data exported without flattening; null from an outer join; an array field mistaken for a scalar.","solutions":["Flatten the row so the placeholder points at a primitive: `{\"userName\":\"Ann\"}` and template `{userName}.mp4`.","Replace null with a sensible default string before rendering.","If you need a nested value, pre-compute it into a top-level scalar key."],"exampleFix":"# before: object value used as a placeholder\n--batch '[{\"user\":{\"name\":\"Ann\"}}]' --output '{user}.mp4'\n\n# after: flatten to a primitive key\n--batch '[{\"userName\":\"Ann\"}]' --output '{userName}.mp4'","handlingStrategy":"type-guard","validationCode":"function flattenPrimitives(row: Record<string, unknown>): Record<string, string|number|boolean> {\n  const out: Record<string, string|number|boolean> = {};\n  for (const [k, v] of Object.entries(row)) {\n    if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') out[k] = v;\n  }\n  return out;\n}","typeGuard":"function isPrimitiveValue(v: unknown): v is string | number | boolean {\n  return typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';\n}","tryCatchPattern":"try {\n  resolveOutputTemplate(template, row, index);\n} catch (err) {\n  if (err instanceof BatchRenderInputError && err.title === 'Invalid output template') {\n    // replace object/null values with primitive defaults, or re-template\n  }\n}","preventionTips":["Flatten nested data into primitive top-level keys before templating.","Coalesce null to a default string before writing the batch.","Reserve placeholders for scalar columns only."],"tags":["cli","validation","batch","templating","type-guard"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}