{"record":{"id":"bed864133c246fb7","repo":"heygen-com/hyperframes","slug":"grading-must-be-valid-hyperframes-color-grading","errorCode":null,"errorMessage":"--grading must be valid HyperFrames color-grading JSON","messagePattern":"--grading must be valid HyperFrames color-grading JSON","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/commands/media-treatment.ts","lineNumber":401,"sourceCode":"      isRecord(value) && isRecord(merged[key]) ? mergeGradingPatch(merged[key], value) : value;\n  }\n  return merged;\n}\n\nfunction serializeGradingPatch(before: unknown, patch: unknown): string | null {\n  assertKnownGradingShape(patch);\n  if (isColorGradingVariableRef(before) && isRecord(patch)) {\n    throw new Error(\"Cannot merge a grading patch into an unresolved whole-grade variable\");\n  }\n  const current =\n    typeof before === \"string\" && !isColorGradingVariableRef(before) ? { preset: before } : before;\n  const grading = mergeGradingPatch(current, patch);\n  assertKnownGradingShape(grading);\n  if (containsColorGradingVariableRef(grading)) {\n    return typeof grading === \"string\" ? grading.trim() : JSON.stringify(grading);\n  }\n  const normalized = normalizeHfColorGrading(grading);\n  if (!normalized) throw new Error(\"--grading must be valid HyperFrames color-grading JSON\");\n  return hasHfColorGradingAuthoredValues(normalized) ? serializeHfColorGrading(normalized) : null;\n}\n\nfunction queryIncludingTemplates(root: Document | Element, selector: string): Element[] {\n  const matches = Array.from(root.querySelectorAll(selector));\n  if (matches.length > 0) return matches;\n  for (const template of root.querySelectorAll(\"template\")) {\n    const nested = queryIncludingTemplates(template, selector);\n    if (nested.length > 0) return nested;\n  }\n  return [];\n}\n\nfunction selectMediaElement(\n  source: string,\n  selector: string,\n  selectorIndex?: number,\n): { element: Element; selectorIndex: number; tag: \"img\" | \"video\" } {","sourceCodeStart":383,"sourceCodeEnd":419,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/cli/src/commands/media-treatment.ts#L383-L419","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Confirm preset ids via `hyperframes media-treatment --capability presets --json` and palette ids via `--capability palettes --json`.","Ensure the grading object has at least one authored value (the hasHfColorGradingAuthoredValues check downstream also requires this).","Run with --dry-run --json to see whether the merged result is empty before writing.","Compare against a known-good example from `--capability <family>` 'apply' blocks."],"exampleFix":"# before -- preset typo passes shape check but fails normalize\nhyperframes media-treatment -s '#hero' --grading '{\"preset\":\"warm-daylite\"}' --apply\n# after\nhyperframes media-treatment -s '#hero' --grading '{\"preset\":\"warm-daylight\"}' --apply","handlingStrategy":"validation","validationCode":"import { normalizeHfColorGrading } from '@hyperframes/core';\n\nfunction normalizesToValid(value: unknown): boolean {\n  return normalizeHfColorGrading(value) !== null;\n}","typeGuard":"import { normalizeHfColorGrading, hasHfColorGradingAuthoredValues } from '@hyperframes/core';\n\nfunction isNormalizableGrading(value: unknown): boolean {\n  const n = normalizeHfColorGrading(value);\n  return n !== null && hasHfColorGradingAuthoredValues(n);\n}","tryCatchPattern":"try {\n  serializeGradingPatch(before, patch);\n} catch (error) {\n  if (/--grading must be valid HyperFrames color-grading JSON/.test(String(error))) {\n    // verify preset/palette ids exist; ensure >=1 authored value; retry\n    throw new Error('Grading normalized to nothing — check preset/palette ids and authored values');\n  }\n  throw error;\n}","preventionTips":["Verify preset ids via --capability presets and palette ids via --capability palettes before use.","Ensure the grading object has at least one authored value (not just a preset that resolves to identity).","Always test with --dry-run --json first."],"tags":["color-grading","validation","media-treatment"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}