heygen-com/hyperframes · error · RangeError

A hue curve supports at most

Error message

A hue curve supports at most ${HF_COLOR_CURVE_MAX_POINTS} points

What it means

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.

Solutions

  1. 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).
  2. Cap additions in the authoring UI so users cannot exceed 16 entries.
  3. Run validateHueCurve() upstream — it rejects length > 16 with the same bound.

Example fix

// before — 36 points, one per 10 degrees
const dense = Array.from({ length: 36 }, (_, i) => [i * 10, f(i * 10)]);
compileHfHueCurve(dense, -1, 1);

// after — decimate to <= 16 representative points
const sparse = dense.filter((_, i) => i % 3 === 0); // 12 points
compileHfHueCurve(sparse, -1, 1);
Defensive patterns

Strategy: validation

Validate before calling

import { HF_COLOR_CURVE_MAX_POINTS } from '@hyperframes/core';

function assertHueCurveMaxPoints(points: readonly unknown[]): void {
  if (points.length > HF_COLOR_CURVE_MAX_POINTS) {
    throw new Error(`Hue curve supports at most ${HF_COLOR_CURVE_MAX_POINTS} points, got ${points.length}`);
  }
}

assertHueCurveMaxPoints(points);

Type guard

function isHueCurveWithinLimit(points: readonly unknown[]): points is [number, number][] {
  return Array.isArray(points) && points.length <= 16;
}

Try / catch

try {
  compileHfHueCurve(points, -1, 1);
} catch (err) {
  if (err instanceof RangeError && /supports at most 16 points/.test(err.message)) {
    // decimate points to <= 16 (e.g. uniform stride) and retry
  } else throw err;
}

Prevention

When it happens

Trigger: 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).

Common situations: 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.

Related errors


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

Appendix: source

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

  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];
    if (!point || point[0] < 0 || point[0] >= 360) {
      throw new RangeError("Hue curve inputs must be from 0 up to 360 degrees");
    }
    if (index > 0 && point[0] === sorted[index - 1]?.[0]) {
      throw new RangeError("Hue curve inputs must be unique");
    }
  }
  const before = sorted.slice(-2).map(([hue, delta]) => [hue - 360, delta] as const);
  const after = sorted.slice(0, 2).map(([hue, delta]) => [hue + 360, delta] as const);
  const periodic = [...before, ...sorted, ...after];
  validateCurvePoints(periodic, size);
  return compileCurveSamples(periodic, size, (index) => (index / size) * 360, outputMin, outputMax);
}

View on GitHub (pinned to c2996c8626)