heygen-com/hyperframes · error · Error

Grade entry ${index + 1} must be an object with label and gr

Error message

Grade entry ${index + 1} must be an object with label and grading

What it means

Thrown by parseGradesFile() while mapping entries: each entry must pass isRecord (a non-null, non-array object). The index in the message is 1-based (index + 1). A null, primitive, or array element is rejected; only plain objects with label + grading are accepted.

Source

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

export function parseGradesFile(filePath: string): GradeCompareCell[] {
  if (!existsSync(filePath)) {
    throw new Error(`Grades file not found: ${filePath}`);
  }

  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) {

View on GitHub (pinned to c2996c8626)

Solutions

  1. Make every array element a plain object with label and grading keys
  2. Remove null/primitive placeholders
  3. If a nested array appears, flatten it into individual grade objects

Example fix

// before (entry is an array, not an object)
[
  ["warm", {}]
]
// after
[
  { "label": "warm", "grading": {} }
]
Defensive patterns

Strategy: type-guard

Validate before calling

function isRecord(v: unknown): v is Record<string, unknown> {
  return typeof v === 'object' && v !== null && !Array.isArray(v);
}
entries.forEach((entry, i) => {
  if (!isRecord(entry)) throw new Error(`entry ${i + 1} must be an object`);
});

Type guard

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

Prevention

When it happens

Trigger: An entry that is null; a string; a number; or an array (e.g. ["warm", {}] instead of [{ label, grading }]).

Common situations: A malformed comma turning two entries into one array; a placeholder null left in the list; exporting a list of names instead of objects.

Related errors


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