heygen-com/hyperframes · error · BatchRenderInputError

--batch must be a JSON array of objects, or an object with a

Error message

--batch must be a JSON array of objects, or an object with a "rows" array.

What it means

BatchRenderInputError with title 'Invalid batch payload', thrown by parseBatchRows when the parsed JSON is neither an array nor an object exposing a 'rows' array. The accepted shapes are exactly: a JSON array of row objects, or { rows: [...] }. Anything else (a bare object without rows, a number, a string) trips this check before any row-level validation.

Source

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

function isRecord(value: unknown): value is Record<string, unknown> {
  return value !== null && typeof value === "object" && !Array.isArray(value);
}

function parseJson(raw: string, source: string): unknown {
  try {
    return JSON.parse(raw);
  } catch (error: unknown) {
    throw new BatchRenderInputError("Invalid JSON in --batch", `${source}: ${errorMessage(error)}`);
  }
}

export function parseBatchRows(raw: string, source: string): Record<string, unknown>[] {
  const parsed = parseJson(raw, source);
  const rows = Array.isArray(parsed) ? parsed : isRecord(parsed) ? parsed.rows : undefined;

  if (!Array.isArray(rows)) {
    throw new BatchRenderInputError(
      "Invalid batch payload",
      '--batch must be a JSON array of objects, or an object with a "rows" array.',
    );
  }
  if (rows.length === 0) {
    throw new BatchRenderInputError("Empty batch", `${source} contains zero rows.`);
  }

  return rows.map((row, index) => {
    if (!isRecord(row)) {
      throw new BatchRenderInputError(
        "Invalid batch row",
        `Row ${index} must be a JSON object of variable values.`,
      );
    }
    return row;
  });
}

View on GitHub (pinned to c2996c8626)

Solutions

  1. Provide a JSON array of row objects: `[{...},{...}]`.
  2. Or wrap in { rows: [...] } if you prefer the envelope shape.
  3. Ensure 'rows' (if used) is actually an array, not a single object.

Example fix

# before: bare object, no rows array
hyperframes render --batch '{"color":"red"}'

# after: array of row objects
hyperframes render --batch '[{"color":"red"},{"color":"blue"}]'
Defensive patterns

Strategy: type-guard

Validate before calling

function normalizeRows(parsed: unknown): unknown[] {
  if (Array.isArray(parsed)) return parsed;
  if (parsed && typeof parsed === 'object' && Array.isArray((parsed as any).rows)) {
    return (parsed as any).rows;
  }
  throw new Error('--batch must be a JSON array of objects or { rows: [...] }');
}

Type guard

function isRowsEnvelope(v: unknown): v is { rows: unknown[] } {
  return !!v && typeof v === 'object' && !Array.isArray(v) && Array.isArray((v as any).rows);
}

Try / catch

try {
  parseBatchRows(raw, source);
} catch (err) {
  if (err instanceof BatchRenderInputError && err.title === 'Invalid batch payload') {
    // re-wrap as [...] or { rows: [...] }
  }
}

Prevention

When it happens

Trigger: Passing --batch '{"color":"red"}' (a single object with no rows array), '--batch "42"', or '--batch "{\"rows\":123}"' (rows present but not an array).

Common situations: Confusing the single-row --vars payload with the multi-row --batch shape; wrapping the array under a different key (e.g. 'data'); passing a top-level object whose rows field is null.

Related errors


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