{"record":{"id":"867a79573cdabe61","repo":"heygen-com/hyperframes","slug":"curve-outputs-must-be-between-outputmin-and-o","errorCode":null,"errorMessage":"Curve outputs must be between ${outputMin} and ${outputMax}","messagePattern":"Curve outputs must be between (.+?) and (.+?)","errorType":"validation","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/colorGradingCurves.ts","lineNumber":98,"sourceCode":"      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,\n  outputMax: number,\n): void {\n  if (!Number.isFinite(outputMin) || !Number.isFinite(outputMax) || outputMin >= outputMax) {\n    throw new RangeError(\"Curve output bounds must be finite and increasing\");\n  }\n  if (points.some(([, output]) => output < outputMin || output > outputMax)) {\n    throw new RangeError(`Curve outputs must be between ${outputMin} and ${outputMax}`);\n  }\n}\n\nfunction interpolateCurveSegment(\n  input: number,\n  start: HfColorCurvePoint,\n  end: HfColorCurvePoint,\n  startTangent: number,\n  endTangent: number,\n): number {\n  const span = end[0] - start[0];\n  const t = Math.min(1, Math.max(0, (input - start[0]) / span));\n  const t2 = t * t;\n  const t3 = t2 * t;\n  return (\n    (2 * t3 - 3 * t2 + 1) * start[1] +\n    (t3 - 2 * t2 + t) * span * startTangent +\n    (-2 * t3 + 3 * t2) * end[1] +","sourceCodeStart":80,"sourceCodeEnd":116,"githubUrl":"https://github.com/heygen-com/hyperframes/blob/c2996c8626135db5253519359d8a063d3bafad8d/packages/core/src/colorGradingCurves.ts#L80-L116","documentation":"validateOutputRange() checks that every point's output lies within [outputMin, outputMax] after the bounds themselves pass. Any point whose output is below outputMin or above outputMax is rejected, with the bounds interpolated. This prevents a curve whose deltas escape the legal shader range (e.g. hue delta beyond [-1,1]) which would clip unpredictably in the GPU sampler.","triggerScenarios":"A hue curve point with delta 2.0 when bounds are [-1, 1]; a point at -1.5 with bounds [-1,1]; bounds tightened after points were authored so existing points now fall outside.","commonSituations":"UI letting a user drag a hue delta beyond the legal range; changing outputMin/outputMax without re-clamping existing points; importing points from a tool with a wider range.","solutions":["Clamp every point's output into [outputMin, outputMax] before compiling.","Align the UI slider limits to the same bounds you pass to compileHfHueCurve."],"exampleFix":"// before\ncompileHfHueCurve([[0, 2.0], [180, 0], [359, -0.5]], -1, 1); // 2.0 > max\n\n// after — clamp outputs into range\nconst clamped = pts.map(([h, d]) => [h, Math.min(1, Math.max(-1, d))] as const);\ncompileHfHueCurve(clamped, -1, 1);","handlingStrategy":"validation","validationCode":"const clamped = points.map(([h, d]) => [h, Math.min(outputMax, Math.max(outputMin, d))] as const);","typeGuard":"function outputsInRange(points: readonly (readonly [number, number])[], min: number, max: number): boolean {\n  return points.every(([, o]) => o >= min && o <= max);\n}","tryCatchPattern":"try { compileHfHueCurve(pts, min, max); }\ncatch (err) { if (/outputs must be between/.test(String(err))) { pts = pts.map(([h,d]) => [h, Math.min(max, Math.max(min, d))] as const); } else throw err; }","preventionTips":["Clamp every output into [outputMin, outputMax] before compiling.","Keep UI slider limits equal to the bounds you pass to compileHfHueCurve."],"tags":["color-grading","curve","validation","range","hue","clamping"],"backgroundTag":null,"analyzedSha":"c2996c8626135db5253519359d8a063d3bafad8d","analyzedAt":"2026-08-12T22:18:56.877Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}