remotion-dev/remotion · error · TypeError

Invalid LUT content: DOMAIN_MIN must be smaller than…

Error message

Invalid LUT content: DOMAIN_MIN must be smaller than DOMAIN_MAX for every channel

What it means

After parsing the header, parseCubeLut() validates that for all three channels DOMAIN_MIN < DOMAIN_MAX (defaults 0/1). If any channel has a min equal to or greater than its max, the LUT domain is inverted or degenerate and cannot be interpreted, so a TypeError is thrown.

Solutions

  1. Open the .cube file and ensure every DOMAIN_MAX value is strictly greater than the corresponding DOMAIN_MIN value
  2. If the domain lines look wrong, delete DOMAIN_MIN/DOMAIN_MAX entirely — the parser defaults to [0,0,0]/[1,1,1]
  3. Re-export the LUT from the original grading/color tool with default domain settings
  4. Validate the header with a quick script before parsing (compare min/max per channel)

Example fix

// before (.cube header)
DOMAIN_MIN 0.0 0.0 0.0
DOMAIN_MAX 0.0 0.0 0.0
// after
DOMAIN_MIN 0.0 0.0 0.0
DOMAIN_MAX 1.0 1.0 1.0
Defensive patterns

Strategy: validation

Validate before calling

const lines = content.split(/\r?\n/).map((l) => l.split('#')[0].trim());
const min = lines.find((l) => l.startsWith('DOMAIN_MIN'));
const max = lines.find((l) => l.startsWith('DOMAIN_MAX'));
if (min && max) {
  const mins = min.split(/\s+/).slice(1).map(Number);
  const maxs = max.split(/\s+/).slice(1).map(Number);
  if (mins.some((m, i) => m >= maxs[i])) throw new Error('DOMAIN_MIN must be < DOMAIN_MAX');
}

Try / catch

try {
  lut = parseCubeLut(content);
} catch (e) {
  if (e instanceof TypeError && e.message.includes('DOMAIN_MIN')) {
    console.error('LUT domain settings are inverted or equal; fix DOMAIN_MIN/DOMAIN_MAX or remove them');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling parseCubeLut(content) on a .cube file whose `DOMAIN_MIN` / `DOMAIN_MAX` triplets are inverted (e.g. DOMAIN_MAX 0.0 0.0 0.0 and DOMAIN_MIN 1.0 1.0 1.0), equal (DOMAIN_MIN == DOMAIN_MAX on any channel), or where only one of the two directives was hand-edited.

Common situations: Corrupted or hand-edited .cube files, LUTs exported from tools with wrong domain settings, concatenating header lines from different LUTs, or typos swapping MIN and MAX values.

Understand the failure class

Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.

Related errors


AI-assisted analysis of remotion-dev/remotion@46a3a6bf13 (2026-09-18). Data as JSON: /api/errors/864424ddf56face5. Report an issue: GitHub.

Appendix: source

Thrown at packages/effects/src/lut/parse-cube-lut.ts:192

		});
		dataStarted = true;
		dataRows++;

		const maxDataRows = size ** 3;
		if (dataRows > maxDataRows) {
			throw new TypeError(
				`Invalid LUT content: expected ${maxDataRows} color rows for LUT_3D_SIZE ${size}, but got more`,
			);
		}
	}

	if (size === null) {
		throw new TypeError('Invalid LUT content: LUT_3D_SIZE is missing');
	}

	for (let channel = 0; channel < 3; channel++) {
		if (domainMin[channel] >= domainMax[channel]) {
			throw new TypeError(
				`Invalid LUT content: DOMAIN_MIN must be smaller than DOMAIN_MAX for every channel`,
			);
		}
	}

	const expectedRows = size ** 3;
	if (dataRows !== expectedRows) {
		throw new TypeError(
			`Invalid LUT content: expected ${expectedRows} color rows for LUT_3D_SIZE ${size}, but got ${dataRows}`,
		);
	}

	const data = new Float32Array(expectedRows * 4);
	let dataIndex = 0;

	for (let index = 0; index < lines.length; index++) {
		const line = stripComment(lines[index]).trim();
		if (line.length === 0) {

View on GitHub (pinned to 46a3a6bf13)