heygen-com/hyperframes · error · CubeLutParseError

LUT_3D_SIZE ${lut3dSize} exceeds max ${maxSize}

Error message

LUT_3D_SIZE ${lut3dSize} exceeds max ${maxSize}

What it means

parseCubeLut clamps the accepted 3D LUT size to options.maxSize, defaulting to DEFAULT_MAX_CUBE_LUT_SIZE (64). The check at line 144 rejects any LUT_3D_SIZE larger than that cap. The bound exists because a size-N 3D LUT allocates N^3 RGB triples (size 65 = 274,625 floats, size 256 = ~16.7M).

Source

Thrown at packages/core/src/colorLuts.ts:145

        throw new CubeLutParseError(`${keyword} expects two numbers`, lineNumber);
      }
      const min = parseFiniteNumber(rest[0]!, lineNumber);
      const max = parseFiniteNumber(rest[1]!, lineNumber);
      if (max <= min) {
        throw new CubeLutParseError("LUT_3D_INPUT_RANGE max must exceed min", lineNumber);
      }
      domainMin = [min, min, min];
      domainMax = [max, max, max];
      continue;
    }
    if (keyword === "LUT_1D_SIZE") {
      lut1dSize = parseSize(rest[0], keyword, lineNumber);
      continue;
    }
    if (keyword === "LUT_3D_SIZE") {
      lut3dSize = parseSize(rest[0], keyword, lineNumber);
      if (lut3dSize > maxSize) {
        throw new CubeLutParseError(`LUT_3D_SIZE ${lut3dSize} exceeds max ${maxSize}`, lineNumber);
      }
      continue;
    }

    if (!isNumericDataLine(keyword)) {
      if (keyword.startsWith("LUT_")) {
        throw new CubeLutParseError(`Unsupported cube keyword ${keyword}`, lineNumber);
      }
      continue;
    }
    if (!lut3dSize) {
      if (lut1dSize) {
        throw new CubeLutParseError("1D cube LUTs are not supported yet", lineNumber);
      }
      throw new CubeLutParseError("LUT data appears before LUT_3D_SIZE", lineNumber);
    }
    if (parts.length !== 3) {
      throw new CubeLutParseError("LUT data rows must contain three numbers", lineNumber);

View on GitHub (pinned to c2996c8626)

Solutions

  1. Raise the cap explicitly via parseCubeLut(text, { maxSize: 256 }) — only do this if you can afford the memory (N^3 * 3 floats).
  2. Re-export the LUT at a smaller size (e.g. 33 or 64) from the source tool.
  3. Stream or downsample the LUT externally before parsing.

Example fix

// before
parseCubeLut(fileText); // throws for LUT_3D_SIZE 128

// after — opt into a larger cap
parseCubeLut(fileText, { maxSize: 256 });
Defensive patterns

Strategy: try-catch

Validate before calling

function chooseMaxSize(fileText: string, hardCap = 512): number {
  const m = /^LUT_3D_SIZE\s+(\d+)/m.exec(fileText);
  const declared = m ? Number(m[1]) : 0;
  if (!Number.isInteger(declared) || declared < 2) return 64;
  return Math.min(Math.max(declared, 64), hardCap);
}

parseCubeLut(fileText, { maxSize: chooseMaxSize(fileText) });

Try / catch

try {
  parseCubeLut(fileText);
} catch (err) {
  if (err instanceof CubeLutParseError && /exceeds max/.test(err.message)) {
    // either re-parse with a higher maxSize, or downsample externally
    const size = Number(/^LUT_3D_SIZE\s+(\d+)/m.exec(fileText)?.[1] ?? 0);
    parseCubeLut(fileText, { maxSize: size });
  } else throw err;
}

Prevention

When it happens

Trigger: Parsing a file whose 'LUT_3D_SIZE N' has N > maxSize (default 64). Common N values from pro color tools: 65, 128, 256.

Common situations: Loading a high-resolution LUT exported from DaVinci Resolve, Lustre, or similar; a default cap that is too low for the asset pipeline.

Related errors


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