heygen-com/hyperframes · error · Error

Grade entry ${index + 1} must have a non-empty string label

Error message

Grade entry ${index + 1} must have a non-empty string label

What it means

Thrown by parseGradesFile() when an entry passes isRecord but its label is not a non-empty string: typeof label !== 'string' (missing, null, number) or label.trim() is empty ("" or whitespace-only). The label drives both the cell caption and the LUT-rewrite lookup, so it must be a real string.

Source

Thrown at packages/cli/src/commands/grade-compare.ts:230

  let parsed: unknown;
  try {
    parsed = JSON.parse(readFileSync(filePath, "utf-8"));
  } catch (err) {
    throw new Error(`Could not parse grades JSON: ${normalizeErrorMessage(err)}`);
  }

  if (!Array.isArray(parsed)) {
    throw new Error("Grades file must be a JSON array of { label, grading } objects");
  }

  return parsed.map((entry, index) => {
    if (!isRecord(entry)) {
      throw new Error(`Grade entry ${index + 1} must be an object with label and grading`);
    }
    const label = entry.label;
    if (typeof label !== "string" || !label.trim()) {
      throw new Error(`Grade entry ${index + 1} must have a non-empty string label`);
    }
    if (!hasOwn(entry, "grading")) {
      throw new Error(`Grade entry "${label}" must include a grading value`);
    }
    return validateCell(label, entry.grading);
  });
}

export function resolveLutCells(luts: string): GradeCompareCell[] {
  const paths = luts
    .split(",")
    .map((part) => part.trim())
    .filter(Boolean);
  if (paths.length === 0) {
    throw new Error("--luts must include at least one LUT path");
  }
  return paths.map((lutPath) =>
    validateCell(basename(lutPath, extname(lutPath)), { lut: { src: lutPath } }),

View on GitHub (pinned to c2996c8626)

Solutions

  1. Add a non-empty string `label` to every entry
  2. Use the exact key name 'label' (not 'name' or 'title')
  3. Trim the value so it is not only whitespace

Example fix

// before
[
  { "name": "warm", "grading": {} }
]
// after
[
  { "label": "warm", "grading": {} }
]
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof entry.label !== 'string' || entry.label.trim().length === 0) {
  throw new Error(`entry ${index + 1} needs a non-empty string label`);
}

Type guard

function hasNonEmptyLabel(entry: unknown): entry is { label: string } {
  return typeof (entry as { label?: unknown })?.label === 'string' &&
    ((entry as { label: string }).label.trim().length > 0);
}

Prevention

When it happens

Trigger: entry.label omitted entirely; label: null or a number; label: "" or " "; using a different key like "name" instead of "label".

Common situations: Using "name" instead of the required "label" key; an empty label from a template; whitespace from copy-paste.

Related errors


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