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
- Open the .cube file and ensure every DOMAIN_MAX value is strictly greater than the corresponding DOMAIN_MIN value
- If the domain lines look wrong, delete DOMAIN_MIN/DOMAIN_MAX entirely — the parser defaults to [0,0,0]/[1,1,1]
- Re-export the LUT from the original grading/color tool with default domain settings
- 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
- Never hand-edit DOMAIN_MIN/DOMAIN_MAX without re-checking min < max per channel
- Remove both domain lines entirely to get the safe 0..1 defaults
- Re-export LUTs from the original tool instead of patching them
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
- Invalid LUT content: expected
- Invalid LUT content: LUT_3D_SIZE is missing
- Invalid LUT content on line
- Combined 1D and 3D LUTs are not supported.
- Conflicting LUT input range headers.
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)