heygen-com/hyperframes · error · Error

Grade entry "${label}" must include a grading value

Error message

Grade entry "${label}" must include a grading value

What it means

Thrown by parseGradesFile when a grades-JSON array entry has a valid `label` string but is missing the `grading` key. Each entry MUST be shaped `{ label, grading }`; the `grading` value is what feeds the color-grading shader, so an entry without it carries nothing to render. The check uses hasOwn, so an explicit `"grading": undefined` also trips it.

Source

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

    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. Open grades.json and add a `grading` object to the entry named in the message, e.g. `{"label":"Warm","grading":{"brightness":0.1}}`.
  2. If unsure of the grading shape, run `hyperframes grade-compare --for frame.png --luts x.cube` once to see a valid cell, or consult the color-grading docs for the accepted keys.
  3. Lint the file before running: every top-level array element must own both `label` (non-empty string) and `grading`.

Example fix

// before — grades.json
[{"label":"Warm"}]
// after
[{"label":"Warm","grading":{"brightness":0.1,"contrast":1.1}}]
Defensive patterns

Strategy: validation

Validate before calling

// Validate a grades file before calling parseGradesFile
import { readFileSync } from "node:fs";
function validateGradesFile(path: string): void {
  const parsed = JSON.parse(readFileSync(path, "utf-8"));
  if (!Array.isArray(parsed)) throw new Error("grades file must be a JSON array");
  for (let i = 0; i < parsed.length; i++) {
    const e = parsed[i];
    if (typeof e !== "object" || e === null || Array.isArray(e))
      throw new Error(`entry ${i + 1} is not an object`);
    if (typeof e.label !== "string" || !e.label.trim())
      throw new Error(`entry ${i + 1} lacks a non-empty label`);
    if (!Object.prototype.hasOwnProperty.call(e, "grading"))
      throw new Error(`entry ${i + 1} ("${e.label}") lacks grading`);
  }
}

Type guard

function isGradeEntry(v: unknown): v is { label: string; grading: unknown } {
  return typeof v === "object" && v !== null && !Array.isArray(v)
    && typeof (v as any).label === "string" && (v as any).label.trim() !== ""
    && Object.prototype.hasOwnProperty.call(v, "grading");
}

Try / catch

try {
  const cells = parseGradesFile(path);
} catch (err) {
  // Surface the message verbatim — it already names the offending entry.
  console.error(String((err as Error).message));
  process.exit(1);
}

Prevention

When it happens

Trigger: Running `hyperframes grade-compare --grades grades.json` where at least one array element looks like `{"label":"Warm"}` (no `grading` key). Also triggered by programmatic callers of the exported parseGradesFile with the same malformed input.

Common situations: Hand-authoring a grades JSON and forgetting the field; renaming `grading` to `grade`/`look`/`preset`; schema drift after a HyperFrames upgrade that renamed the key; copy-pasting a partial object.

Related errors


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