{"record":{"id":"97b28de6758b701c","repo":"heygen-com/hyperframes","slug":"a-color-curve-requires-at-least-two-points","errorCode":null,"errorMessage":"A color curve requires at least two points","messagePattern":"A color curve requires at least two points","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/colorGradingCurves.ts","lineNumber":73,"sourceCode":"\n  for (let index = 1; index < points.length - 1; index += 1) {\n    const before = valueAt(slopes, index - 1);\n    const after = valueAt(slopes, index);\n    if (before === 0 || after === 0 || Math.sign(before) !== Math.sign(after)) {\n      result[index] = 0;\n      continue;\n    }\n    const beforeSpan = valueAt(spans, index - 1);\n    const afterSpan = valueAt(spans, index);\n    const beforeWeight = 2 * afterSpan + beforeSpan;\n    const afterWeight = afterSpan + 2 * beforeSpan;\n    result[index] = (beforeWeight + afterWeight) / (beforeWeight / before + afterWeight / after);\n  }\n  return result;\n}\n\nfunction validateCurvePoints(points: readonly HfColorCurvePoint[], size: number): void {\n  if (points.length < 2) throw new RangeError(\"A color curve requires at least two points\");\n  if (!Number.isInteger(size) || size < 2) {\n    throw new RangeError(\"Curve LUT size must be at least 2\");\n  }\n  let previousInput = Number.NEGATIVE_INFINITY;\n  for (const [input, output] of points) {\n    if (!Number.isFinite(input) || !Number.isFinite(output)) {\n      throw new TypeError(\"Color curve points must be finite\");\n    }\n    if (input <= previousInput) {\n      throw new RangeError(\"Color curve inputs must be strictly increasing\");\n    }\n    previousInput = input;\n  }\n}\n\nfunction validateOutputRange(\n  points: readonly HfColorCurvePoint[],\n  outputMin: number,","sourceCodeStart":55,"sourceCodeEnd":91,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/core/src/colorGradingCurves.ts#L55-L91","documentation":"validateCurvePoints() requires at least two control points to interpolate a curve; fewer than two is rejected as a RangeError. A single point (or zero) cannot define a segment, so cubic Hermite interpolation — which needs a start and end — has nothing to operate on. Applies to both compileHfColorCurve and the periodic hue path (which extends points but still calls validateCurvePoints).","triggerScenarios":"Calling compileHfColorCurve([]) or compileHfColorCurve([[0,0]]) with 0 or 1 points; a UI that lets a user clear all but one point and then renders.","commonSituations":"A color-grade tool defaulting to an empty points array before the user adds any; programmatic curve construction that forgot endpoints; a deserialization that dropped points.","solutions":["Supply at least two points; for a color curve the canonical minimum is the two endpoints [[0,0],[1,1]] (identity).","Guard in the UI: disable render until the user has placed >= 2 points."],"exampleFix":"// before\nconst lut = compileHfColorCurve([[0, 0]]); // < 2 points\n\n// after — identity curve with both endpoints\nconst lut = compileHfColorCurve([[0, 0], [1, 1]]);","handlingStrategy":"validation","validationCode":"if (points.length < 2) throw new Error('need >= 2 curve points');\n// or default to the identity curve\nconst safe = points.length >= 2 ? points : [[0,0],[1,1]] as const;","typeGuard":"function hasEnoughPoints<T>(pts: readonly T[]): pts is [T, T, ...T[]] {\n  return pts.length >= 2;\n}","tryCatchPattern":"try { compileHfColorCurve(pts); }\ncatch (err) { if (/at least two points/.test(String(err))) { pts = [[0,0],[1,1]]; } else throw err; }","preventionTips":["Default to the identity endpoints [[0,0],[1,1]] when no points are authored.","Disable render in the UI until >= 2 points exist."],"tags":["color-grading","curve","validation","range"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}