heygen-com/hyperframes · error · CubeLutParseError

LUT data rows must contain three numbers

Error message

LUT data rows must contain three numbers

What it means

Each 3D LUT data row must carry exactly three numeric tokens (R, G, B). The throw at line 163 fires when a numeric data line splits into a token count other than three. It runs after LUT_3D_SIZE is known, so it only applies to genuine data rows.

Source

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

        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);
    }
    rows.push(
      parseFiniteNumber(parts[0]!, lineNumber),
      parseFiniteNumber(parts[1]!, lineNumber),
      parseFiniteNumber(parts[2]!, lineNumber),
    );
  }

  if (lut1dSize && lut3dSize) {
    throw new CubeLutParseError("Mixed 1D and 3D cube LUTs are not supported yet");
  }
  if (!lut3dSize) {
    if (lut1dSize) throw new CubeLutParseError("1D cube LUTs are not supported yet");
    throw new CubeLutParseError("Missing LUT_3D_SIZE");
  }
  validateDomain(domainMin, domainMax);

  const expectedRows = lut3dSize * lut3dSize * lut3dSize;

View on GitHub (pinned to c2996c8626)

Solutions

  1. Ensure every data row has exactly three numeric values separated by whitespace.
  2. If the source is RGBA, drop the fourth column before parsing.
  3. Normalize repeated whitespace (e.g. text.replace(/\s+/g, ' ')) and re-check.

Example fix

// before
0.10 0.20 0.30 1.00

// after
0.10 0.20 0.30
Defensive patterns

Strategy: try-catch

Validate before calling

function assertDataRowsAreTriples(fileText: string): void {
  for (const line of fileText.split(/\r?\n/)) {
    const tok = line.trim().split(/\s+/)[0] ?? '';
    if (/^[+-]?(?:\d|\.\d)/.test(tok) && line.trim().split(/\s+/).length !== 3) {
      throw new Error('Each data row must have exactly three numbers');
    }
  }
}

Try / catch

try {
  parseCubeLut(fileText);
} catch (err) {
  if (err instanceof CubeLutParseError && /must contain three numbers/.test(err.message)) {
    // report err.lineNumber; if RGBA, strip the 4th column and retry
  } else throw err;
}

Prevention

When it happens

Trigger: A row like '0.1 0.2' (two channels), '0.1 0.2 0.3 0.4' (four — e.g. RGBA), or a row where a stray whitespace token inflated the count.

Common situations: RGBA exports from a tool that appends alpha; a missing channel from a truncated row; an extra blank-ish token (tab sequences) producing an empty string in the split.

Related errors


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