heygen-com/hyperframes · error · Error

Cannot merge a grading patch into an unresolved whole-grade

Error message

Cannot merge a grading patch into an unresolved whole-grade variable

What it means

Thrown by serializeGradingPatch() in packages/cli/src/commands/media-treatment.ts:388. Before merging, it checks: if the existing stored value (before) is a color-grading variable reference (a '${...}' string) AND the incoming patch is a record/object, it refuses to merge. A variable ref is an opaque whole-grade slot; merging partial keys into it would silently drop the reference.

Source

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

  } catch {
    return raw;
  }
}

function mergeGradingPatch(current: unknown, patch: unknown): unknown {
  if (!isRecord(current) || !isRecord(patch)) return patch;
  const merged = { ...current };
  for (const [key, value] of Object.entries(patch)) {
    merged[key] =
      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);

View on GitHub (pinned to c2996c8626)

Solutions

  1. Clear the existing ref first: `--clear`, then apply a fresh full grading object.
  2. Or supply a complete grading object that wholesale replaces the variable ref instead of a partial patch.
  3. Resolve the variable to concrete values at the source (where it's defined) and re-apply.
  4. If you intended to keep the variable, edit the variable definition directly rather than the element attribute.

Example fix

# element currently: <img data-hf-color-grading="${grade.hero}">
# before -- refused
hyperframes media-treatment -s '#hero' --grading '{"wheels":{...}}' --apply
# after -- clear the ref, then apply a full object
hyperframes media-treatment -s '#hero' --clear
hyperframes media-treatment -s '#hero' --grading '{"preset":"warm-daylight","intensity":0.6}' --apply
Defensive patterns

Strategy: type-guard

Validate before calling

import { isColorGradingVariableRef } from '@hyperframes/parsers/color-grading-contract';
import { parseStoredGrading } from './grading.js';

function canMergeInto(before: unknown, patch: unknown): boolean {
  return !(isColorGradingVariableRef(before) && patch !== null && typeof patch === 'object');
}

Type guard

import { isColorGradingVariableRef } from '@hyperframes/parsers/color-grading-contract';

function isWholeGradeVariableRef(value: unknown): value is string {
  return isColorGradingVariableRef(value);
}

Try / catch

try {
  serializeGradingPatch(before, patch);
} catch (error) {
  if (/Cannot merge a grading patch into an unresolved whole-grade variable/.test(String(error))) {
    // clear the ref first, then apply a full replacement object
    serializeGradingPatch(null, fullGradingObject);
  } else throw error;
}

Prevention

When it happens

Trigger: The target element's data-hf-color-grading attribute is a variable reference (e.g. "${grade.hero}"), and you call --apply with --grading as an object patch without first clearing the ref.

Common situations: Composition authored with reusable grade variables; an agent trying to tune one control on an element that's already bound to a variable; refactoring a project that uses palette/grade variables.

Related errors


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