heygen-com/hyperframes · error · RangeError

Color curves must include input endpoints 0 and 1

Error message

Color curves must include input endpoints 0 and 1

What it means

compileHfColorCurve compiles a shape-preserving cubic spline into a 1024-texel LUT that maps normalized input in [0,1] to output. The check at line 165 enforces that the first control point's input is exactly 0 and the last is exactly 1, so the curve spans the full tonal range (pure black to pure white). Without both anchors the sampler has no segment covering inputs below the first point or above the last, leaving LUT texels undefined at the extremes.

Source

Thrown at packages/core/src/colorGradingCurves.ts:165

    samples[index] = Math.min(outputMax, Math.max(outputMin, output));
  }
  return samples;
}

/** Samples a shape-preserving cubic curve into a GPU-ready 1D lookup table. */
export function compileHfColorCurve(
  points: readonly HfColorCurvePoint[],
  size = HF_COLOR_CURVE_LUT_SIZE,
): Float32Array {
  validateCurvePoints(points, size);
  if (points.length > HF_COLOR_CURVE_MAX_POINTS) {
    throw new RangeError(`A color curve supports at most ${HF_COLOR_CURVE_MAX_POINTS} points`);
  }
  if (points.some(([input]) => input < 0 || input > 1)) {
    throw new RangeError("Color curve inputs must be between 0 and 1");
  }
  if (points[0]?.[0] !== 0 || points[points.length - 1]?.[0] !== 1) {
    throw new RangeError("Color curves must include input endpoints 0 and 1");
  }
  return compileCurveSamples(points, size, (index) => index / (size - 1), 0, 1);
}

/** Samples a periodic hue curve without duplicating the 0/360-degree texel. */
export function compileHfHueCurve(
  points: readonly HfHueCurvePoint[],
  outputMin: number,
  outputMax: number,
  size = HF_COLOR_CURVE_LUT_SIZE,
): Float32Array {
  if (points.length < 3) throw new RangeError("A hue curve requires at least three points");
  if (points.length > HF_COLOR_CURVE_MAX_POINTS) {
    throw new RangeError(`A hue curve supports at most ${HF_COLOR_CURVE_MAX_POINTS} points`);
  }
  const sorted = [...points].sort((a, b) => a[0] - b[0]);
  for (let index = 0; index < sorted.length; index += 1) {
    const point = sorted[index];

View on GitHub (pinned to c2996c8626)

Solutions

  1. Prepend [0, <output at black>] and append [1, <output at white>] so both endpoints are present.
  2. If you want the curve to pass through the first user point's value, set the prepended [0, ...] output equal to that value (likewise for the appended [1, ...]).
  3. Run the upstream validateCurve() from @hyperframes/parsers/color-grading-contract first — it reports missing endpoints and inferred-count overflow before you reach compileHfColorCurve.
  4. Sort points ascending by input before adding anchors; validateCurvePoints requires strictly increasing inputs.

Example fix

// before
compileHfColorCurve([[0.25, 0.18], [0.75, 0.82]]);

// after
compileHfColorCurve([
  [0, 0],
  [0.25, 0.18],
  [0.75, 0.82],
  [1, 1],
]);
Defensive patterns

Strategy: validation

Validate before calling

function assertColorCurveEndpoints(points: readonly [number, number][]): void {
  if (points.length === 0 || points[0][0] !== 0 || points[points.length - 1][0] !== 1) {
    throw new Error('Color curve must start at input 0 and end at input 1');
  }
}

assertColorCurveEndpoints(points);
compileHfColorCurve(points);

Type guard

function isAnchoredColorCurve(points: readonly unknown[]): points is [number, number][] {
  return (
    points.length >= 2 &&
    Array.isArray(points[0]) && points[0][0] === 0 &&
    Array.isArray(points[points.length - 1]) && points[points.length - 1][0] === 1
  );
}

Try / catch

try {
  const lut = compileHfColorCurve(points);
} catch (err) {
  if (err instanceof RangeError && err.message === 'Color curves must include input endpoints 0 and 1') {
    // synthesize anchors and retry, or surface a user-facing validation message
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling compileHfColorCurve(points) where points[0][0] !== 0 or points[points.length-1][0] !== 1, after validateCurvePoints has already accepted the array as finite and strictly increasing. Example: [[0.25, 0.18], [0.75, 0.82]] — no anchor at 0 or 1.

Common situations: Forgetting to add black/white anchors when hand-authoring a curve; loading a preset authored in an external editor that emits only interior control points; a UI that lets users drag interior handles but never synthesizes endpoint anchors before compile.

Related errors


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