heygen-com/hyperframes · error · BatchRenderInputError

Placeholder {${key}} in row ${index} must resolve to a strin

Error message

Placeholder {${key}} in row ${index} must resolve to a string, number, or boolean.

What it means

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.

Source

Thrown at packages/cli/src/commands/batchRender.ts:138

    return row;
  });
}

function placeholderValue(row: Record<string, unknown>, key: string, index: number): string {
  if (key === "index") return String(index);
  if (!Object.hasOwn(row, key)) {
    throw new BatchRenderInputError(
      "Invalid output template",
      `Missing value for placeholder {${key}} in row ${index}.`,
    );
  }

  const value = row[key];
  if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
    return String(value);
  }

  throw new BatchRenderInputError(
    "Invalid output template",
    `Placeholder {${key}} in row ${index} must resolve to a string, number, or boolean.`,
  );
}

export function resolveOutputTemplate(
  template: string,
  row: Record<string, unknown>,
  index: number,
): string {
  return template.replace(PLACEHOLDER_RE, (_match, key: string) =>
    placeholderValue(row, key, index),
  );
}

function isSameOrChildPath(path: string, parent: string): boolean {
  return path === parent || path.startsWith(parent.endsWith(sep) ? parent : parent + sep);
}

View on GitHub (pinned to c2996c8626)

Solutions

  1. Flatten the row so the placeholder points at a primitive: `{"userName":"Ann"}` and template `{userName}.mp4`.
  2. Replace null with a sensible default string before rendering.
  3. If you need a nested value, pre-compute it into a top-level scalar key.

Example fix

# before: object value used as a placeholder
--batch '[{"user":{"name":"Ann"}}]' --output '{user}.mp4'

# after: flatten to a primitive key
--batch '[{"userName":"Ann"}]' --output '{userName}.mp4'
Defensive patterns

Strategy: type-guard

Validate before calling

function flattenPrimitives(row: Record<string, unknown>): Record<string, string|number|boolean> {
  const out: Record<string, string|number|boolean> = {};
  for (const [k, v] of Object.entries(row)) {
    if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean') out[k] = v;
  }
  return out;
}

Type guard

function isPrimitiveValue(v: unknown): v is string | number | boolean {
  return typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';
}

Try / catch

try {
  resolveOutputTemplate(template, row, index);
} catch (err) {
  if (err instanceof BatchRenderInputError && err.title === 'Invalid output template') {
    // replace object/null values with primitive defaults, or re-template
  }
}

Prevention

When it happens

Trigger: 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.

Common situations: Nested data exported without flattening; null from an outer join; an array field mistaken for a scalar.

Related errors


AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12). Data as JSON: /api/errors/57a91899d7b1b403. Report an issue: GitHub.