{"record":{"id":"7e91ad8760ac5bab","repo":"heygen-com/hyperframes","slug":"a-hue-curve-supports-at-most-hf-color-curve-max","errorCode":null,"errorMessage":"A hue curve supports at most ${HF_COLOR_CURVE_MAX_POINTS} points","messagePattern":"A hue curve supports at most (.+?) points","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/colorGradingCurves.ts","lineNumber":179,"sourceCode":"  if (points.some(([input]) => input < 0 || input > 1)) {\n    throw new RangeError(\"Color curve inputs must be between 0 and 1\");\n  }\n  if (points[0]?.[0] !== 0 || points[points.length - 1]?.[0] !== 1) {\n    throw new RangeError(\"Color curves must include input endpoints 0 and 1\");\n  }\n  return compileCurveSamples(points, size, (index) => index / (size - 1), 0, 1);\n}\n\n/** Samples a periodic hue curve without duplicating the 0/360-degree texel. */\nexport function compileHfHueCurve(\n  points: readonly HfHueCurvePoint[],\n  outputMin: number,\n  outputMax: number,\n  size = HF_COLOR_CURVE_LUT_SIZE,\n): Float32Array {\n  if (points.length < 3) throw new RangeError(\"A hue curve requires at least three points\");\n  if (points.length > HF_COLOR_CURVE_MAX_POINTS) {\n    throw new RangeError(`A hue curve supports at most ${HF_COLOR_CURVE_MAX_POINTS} points`);\n  }\n  const sorted = [...points].sort((a, b) => a[0] - b[0]);\n  for (let index = 0; index < sorted.length; index += 1) {\n    const point = sorted[index];\n    if (!point || point[0] < 0 || point[0] >= 360) {\n      throw new RangeError(\"Hue curve inputs must be from 0 up to 360 degrees\");\n    }\n    if (index > 0 && point[0] === sorted[index - 1]?.[0]) {\n      throw new RangeError(\"Hue curve inputs must be unique\");\n    }\n  }\n  const before = sorted.slice(-2).map(([hue, delta]) => [hue - 360, delta] as const);\n  const after = sorted.slice(0, 2).map(([hue, delta]) => [hue + 360, delta] as const);\n  const periodic = [...before, ...sorted, ...after];\n  validateCurvePoints(periodic, size);\n  return compileCurveSamples(periodic, size, (index) => (index / size) * 360, outputMin, outputMax);\n}\n","sourceCodeStart":161,"sourceCodeEnd":197,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/core/src/colorGradingCurves.ts#L161-L197","documentation":"Both color and hue curves share the cap COLOR_GRADING_MAX_CURVE_POINTS (currently 16). The check at line 178 rejects hue curves longer than this because the GPU LUT pipeline and the upstream contract schema reserve a fixed budget per curve. Each point also seeds periodic padding (two clones before, two after), so the working array is longer than the input.","triggerScenarios":"Calling compileHfHueCurve with points.length > 16. Common when generating a dense hue shift procedurally (e.g. sampling a function every 10 degrees yields 36 points).","commonSituations":"Procedurally generated hue tables; importing a hue preset from a tool that emits one point per degree; accumulating user-added points without bounding the count.","solutions":["Reduce the array to at most 16 points by picking representative hues or running a simplification pass (e.g. Ramer-Douglas-Peucker on the hue/delta polyline).","Cap additions in the authoring UI so users cannot exceed 16 entries.","Run validateHueCurve() upstream — it rejects length > 16 with the same bound."],"exampleFix":"// before — 36 points, one per 10 degrees\nconst dense = Array.from({ length: 36 }, (_, i) => [i * 10, f(i * 10)]);\ncompileHfHueCurve(dense, -1, 1);\n\n// after — decimate to <= 16 representative points\nconst sparse = dense.filter((_, i) => i % 3 === 0); // 12 points\ncompileHfHueCurve(sparse, -1, 1);","handlingStrategy":"validation","validationCode":"import { HF_COLOR_CURVE_MAX_POINTS } from '@hyperframes/core';\n\nfunction assertHueCurveMaxPoints(points: readonly unknown[]): void {\n  if (points.length > HF_COLOR_CURVE_MAX_POINTS) {\n    throw new Error(`Hue curve supports at most ${HF_COLOR_CURVE_MAX_POINTS} points, got ${points.length}`);\n  }\n}\n\nassertHueCurveMaxPoints(points);","typeGuard":"function isHueCurveWithinLimit(points: readonly unknown[]): points is [number, number][] {\n  return Array.isArray(points) && points.length <= 16;\n}","tryCatchPattern":"try {\n  compileHfHueCurve(points, -1, 1);\n} catch (err) {\n  if (err instanceof RangeError && /supports at most 16 points/.test(err.message)) {\n    // decimate points to <= 16 (e.g. uniform stride) and retry\n  } else throw err;\n}","preventionTips":["Cap the authoring UI at 16 hue entries.","Run a simplification pass (Ramer-Douglas-Peucker) on procedurally generated hue tables.","Pre-validate with validateHueCurve() to surface the overflow with a path."],"tags":["color-grading","hue-curve","limits","range-error"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}