remotion-dev/remotion · error

LUT header after color data on line

Error message

LUT header after color data on line ${index + 1}.

What it means

parseCubeLut parses .cube LUT files and requires all header keywords (TITLE, LUT_3D_SIZE, DOMAIN_MIN, etc.) to appear before any color data lines. A header keyword found after color rows has started means a malformed file, so it throws with the offending line number.

Solutions

  1. Edit the .cube file so all header keywords (TITLE, LUT_*_SIZE, DOMAIN_MIN/MAX) come before the color data.
  2. Re-export the LUT from its original tool in valid .cube format.
  3. Check the reported line number and remove or move the misplaced header line.
  4. Validate the file with another .cube parser to locate structural problems.

Example fix

// before (broken)
0.1 0.2 0.3
LUT_3D_SIZE 2
// after
LUT_3D_SIZE 2
0.1 0.2 0.3
Defensive patterns

Strategy: validation

Validate before calling

const headerRe = /^[A-Z][A-Z0-9_]*$/;
let seenData = false;
for (const [i, line] of lines.entries()) {
  const kw = line.split(/\s+/)[0];
  if (seenData && headerRe.test(kw)) throw new Error(`Header after data at line ${i + 1}`);
  if (/^[\d.-]+\s+[\d.-]+\s+[\d.-]+$/.test(line)) seenData = true;
}

Type guard

null

Try / catch

try {
  parseCubeLut(text);
} catch (err) {
  if (err.message.includes('header after color data')) {
    // show file/line error to user or attempt reordering repair
  }
}

Prevention

When it happens

Trigger: Loading a .cube file where a line matching /^[A-Z][A-Z0-9_]*$/ appears after numeric color rows — e.g. LUT_3D_SIZE or DOMAIN_MAX declared below the data table, or a data line accidentally formatted as an uppercase keyword.

Common situations: Hand-edited LUT files with the size header moved below the data; LUTs exported by broken tools; concatenated LUT files with a second header block at the end.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at packages/studio/src/helpers/cube-lut.ts:35

	let domainMax: Rgb = [1, 1, 1];
	let data: Float32Array | null = null;
	let offset = 0;
	const headers = new Set<string>();

	for (const [index, rawLine] of text.split(/\r\n?|\n/).entries()) {
		const line = rawLine.trim();
		if (!line || line.startsWith('#')) {
			continue;
		}

		const titleMatch = line.match(/^TITLE\s+"([^"]*)"\s*(?:#.*)?$/);
		const [keyword, ...values] = line.replace(/#.*$/, '').trim().split(/\s+/);
		const numbers = values.map(Number);
		const isHeader = /^[A-Z][A-Z0-9_]*$/.test(keyword);

		if (isHeader) {
			if (offset > 0) {
				throw new Error(`LUT header after color data on line ${index + 1}.`);
			}

			if (headers.has(keyword)) {
				throw new Error(`Duplicate ${keyword} on line ${index + 1}.`);
			}

			headers.add(keyword);
		}

		if (keyword === 'TITLE' && titleMatch) {
			title = titleMatch[1];
			continue;
		}

		if (keyword === 'LUT_1D_SIZE' || keyword === 'LUT_3D_SIZE') {
			if (type !== null) {
				throw new Error('Combined 1D and 3D LUTs are not supported.');
			}

View on GitHub (pinned to 46a3a6bf13)