remotion-dev/remotion · error · TypeError

Invalid LUT content: LUT_3D_SIZE is missing

Error message

Invalid LUT content: LUT_3D_SIZE is missing

What it means

parseCubeLut() parses .cube 3D LUT files and requires a `LUT_3D_SIZE <n>` header directive, which tells the parser the LUT grid dimension (n^3 color rows). If the whole file has been scanned and no LUT_3D_SIZE directive was found, the parser throws this TypeError because the row count and data layout cannot be determined.

Solutions

  1. Add a valid `LUT_3D_SIZE <n>` directive to the file header before the color data, where n matches the cube size
  2. Verify the file actually is a .cube LUT and not a 1D LUT (.cube 1D uses LUT_1D_SIZE, which is rejected earlier) — obtain a 3D LUT instead
  3. Check that the LUT_3D_SIZE line is not commented out (no `#` before it) and the keyword casing is exactly `LUT_3D_SIZE`
  4. Make sure the content loaded is plain text (e.g. `await fetch(url).then(r => r.text())`, not `.arrayBuffer()`), and not an error page

Example fix

// before
const lut = parseCubeLut(fileContents); // file has no LUT_3D_SIZE line
// after
// add to the .cube file header:
// TITLE "My LUT"
// LUT_3D_SIZE 33
// then:
const lut = parseCubeLut(fileContents);
Defensive patterns

Strategy: validation

Validate before calling

const hasSize = /^LUT_3D_SIZE\s+\d+\s*$/m.test(content.replace(/#[^\n\"]*/g, ''));
if (!hasSize) throw new Error('Not a 3D .cube LUT: missing LUT_3D_SIZE');

Type guard

const is3dCubeLut = (content: string): boolean =>
  content.split(/\r?\n/).some((line) => /^LUT_3D_SIZE\s+\d+$/.test(line.trim().split('#')[0].trim()));

Try / catch

let lut;
try {
  lut = parseCubeLut(content);
} catch (e) {
  if (e instanceof TypeError && e.message.includes('LUT_3D_SIZE is missing')) {
    throw new Error('File is not a 3D .cube LUT (no LUT_3D_SIZE header)');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling parseCubeLut(content) with a string that lacks any `LUT_3D_SIZE` line — e.g. a 1D LUT without a size directive, a file where the directive is commented out (anything after an unquoted `#` is stripped), a typo like `LUT_3D_Size` (case-sensitive keyword), or a completely unrelated/empty string passed as LUT content.

Common situations: Loading a .cube file downloaded from the wrong format (1D curves vs 3D LUTs), hand-edited LUT files where the header was accidentally deleted, fetching a LUT over the network and receiving an HTML error page instead of the file, or passing a base64/binary LUT format instead of ASCII .cube text.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


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

Appendix: source

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

		parseTriplet({
			values: [keyword, ...values],
			lineNumber,
			label: 'color row',
		});
		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);

View on GitHub (pinned to 46a3a6bf13)