heygen-com/hyperframes · error · Error

--grading must be valid HyperFrames color-grading JSON

Error message

--grading must be valid HyperFrames color-grading JSON

What it means

Thrown by serializeGradingPatch() in packages/cli/src/commands/media-treatment.ts:401. After the patch passes contract validation and is merged, normalizeHfColorGrading is called; if it returns null (the merged shape can't be normalized into a valid HyperFrames grading object), this fires. It is the semantic fallback for shapes that are structurally OK but semantically empty or incompatible.

Source

Thrown at packages/cli/src/commands/media-treatment.ts:401

      isRecord(value) && isRecord(merged[key]) ? mergeGradingPatch(merged[key], value) : value;
  }
  return merged;
}

function serializeGradingPatch(before: unknown, patch: unknown): string | null {
  assertKnownGradingShape(patch);
  if (isColorGradingVariableRef(before) && isRecord(patch)) {
    throw new Error("Cannot merge a grading patch into an unresolved whole-grade variable");
  }
  const current =
    typeof before === "string" && !isColorGradingVariableRef(before) ? { preset: before } : before;
  const grading = mergeGradingPatch(current, patch);
  assertKnownGradingShape(grading);
  if (containsColorGradingVariableRef(grading)) {
    return typeof grading === "string" ? grading.trim() : JSON.stringify(grading);
  }
  const normalized = normalizeHfColorGrading(grading);
  if (!normalized) throw new Error("--grading must be valid HyperFrames color-grading JSON");
  return hasHfColorGradingAuthoredValues(normalized) ? serializeHfColorGrading(normalized) : null;
}

function queryIncludingTemplates(root: Document | Element, selector: string): Element[] {
  const matches = Array.from(root.querySelectorAll(selector));
  if (matches.length > 0) return matches;
  for (const template of root.querySelectorAll("template")) {
    const nested = queryIncludingTemplates(template, selector);
    if (nested.length > 0) return nested;
  }
  return [];
}

function selectMediaElement(
  source: string,
  selector: string,
  selectorIndex?: number,
): { element: Element; selectorIndex: number; tag: "img" | "video" } {

View on GitHub (pinned to c2996c8626)

Solutions

  1. Confirm preset ids via `hyperframes media-treatment --capability presets --json` and palette ids via `--capability palettes --json`.
  2. Ensure the grading object has at least one authored value (the hasHfColorGradingAuthoredValues check downstream also requires this).
  3. Run with --dry-run --json to see whether the merged result is empty before writing.
  4. Compare against a known-good example from `--capability <family>` 'apply' blocks.

Example fix

# before -- preset typo passes shape check but fails normalize
hyperframes media-treatment -s '#hero' --grading '{"preset":"warm-daylite"}' --apply
# after
hyperframes media-treatment -s '#hero' --grading '{"preset":"warm-daylight"}' --apply
Defensive patterns

Strategy: validation

Validate before calling

import { normalizeHfColorGrading } from '@hyperframes/core';

function normalizesToValid(value: unknown): boolean {
  return normalizeHfColorGrading(value) !== null;
}

Type guard

import { normalizeHfColorGrading, hasHfColorGradingAuthoredValues } from '@hyperframes/core';

function isNormalizableGrading(value: unknown): boolean {
  const n = normalizeHfColorGrading(value);
  return n !== null && hasHfColorGradingAuthoredValues(n);
}

Try / catch

try {
  serializeGradingPatch(before, patch);
} catch (error) {
  if (/--grading must be valid HyperFrames color-grading JSON/.test(String(error))) {
    // verify preset/palette ids exist; ensure >=1 authored value; retry
    throw new Error('Grading normalized to nothing — check preset/palette ids and authored values');
  }
  throw error;
}

Prevention

When it happens

Trigger: A --grading value that passes validateColorGradingContract but fails normalization: a preset id that doesn't exist, an object that normalizes to zero authored values, or a combination that yields nothing serializeHfColorGrading can emit.

Common situations: Preset name typo (valid shape, unknown preset); empty object after merge; referencing a palette id that doesn't resolve; values that the normalizer collapses to identity/no-op.

Related errors


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