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
- Edit the .cube file so all header keywords (TITLE, LUT_*_SIZE, DOMAIN_MIN/MAX) come before the color data.
- Re-export the LUT from its original tool in valid .cube format.
- Check the reported line number and remove or move the misplaced header line.
- 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
- Validate .cube structure before loading (headers first)
- Never hand-edit header positions in LUT files
- Re-export from trusted tools rather than editing exported files
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
- Combined 1D and 3D LUTs are not supported.
- Duplicate on line .
- Expected LUT colors, got more.
- Expected LUT colors, got .
- Expected LUT_1D_SIZE or LUT_3D_SIZE.
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)