remotion-dev/remotion · error

LUT input ranges must be finite.

Error message

LUT input ranges must be finite.

What it means

Even when max > min per channel, the parser additionally requires each channel's range (domainMax[channel] - domainMin[channel]) to be finite — guarding against Infinity or -Infinity bound values whose difference is NaN (Infinity - Infinity) or Infinity. Such domains would produce NaN lookup positions in applyCubeLut and corrupt every pixel. The default domain is [0,0,0]-[1,1,1], so this only fires when custom headers introduce non-finite bounds.

Solutions

  1. Replace Infinity bounds with large finite values (e.g. -1000 and 1000).
  2. Clamp the domain to the realistic input range, typically 'DOMAIN_MIN 0 0 0' / 'DOMAIN_MAX 1 1 1'.
  3. Fix the generator/converter to emit finite numbers only.
  4. Filter the text: reject lines containing Infinity/NaN before calling parseCubeLut.

Example fix

// before
DOMAIN_MIN -Infinity -Infinity -Infinity
DOMAIN_MAX Infinity Infinity Infinity
// after
DOMAIN_MIN 0 0 0
DOMAIN_MAX 1 1 1
Defensive patterns

Strategy: validation

Validate before calling

if (/\b(Infinity|NaN)\b/.test(text)) {
  throw new Error('LUT contains non-finite numbers');
}

Type guard

const hasFiniteDomain = (min: number[], max: number[]): boolean =>
  min.every(Number.isFinite) && max.every(Number.isFinite) &&
  min.every((m, i) => Number.isFinite(max[i] - m));

Try / catch

try {
  const lut = parseCubeLut(text);
} catch (e) {
  if (/must be finite/.test((e as Error).message)) {
    console.error('LUT domain uses Infinity — clamp to a finite range');
  }
}

Prevention

When it happens

Trigger: parseCubeLut(text) where DOMAIN_MIN and DOMAIN_MAX both use Infinity (difference NaN), e.g. 'DOMAIN_MIN -Infinity -Infinity -Infinity' with 'DOMAIN_MAX Infinity Infinity Infinity', or a DOMAIN header pairing ±Infinity values.

Common situations: Generated LUT files that serialized unbounded domains as Infinity instead of large finite numbers; JSON-to-cube converters passing through Infinity; mathematically 'unbounded' LUT ideas written literally.

Understand the failure class

Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.

Related errors


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

Appendix: source

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

		throw new Error('Expected LUT_1D_SIZE or LUT_3D_SIZE.');
	}

	if (offset !== data.length) {
		throw new Error(
			`Expected ${data.length / 3} LUT colors, got ${offset / 3}.`,
		);
	}

	if (domainMin.some((min, channel) => min >= domainMax[channel])) {
		throw new Error(
			'DOMAIN_MAX must be greater than DOMAIN_MIN in every channel.',
		);
	}

	if (
		domainMin.some((min, channel) => !Number.isFinite(domainMax[channel] - min))
	) {
		throw new Error('LUT input ranges must be finite.');
	}

	if (
		(headers.has('LUT_1D_INPUT_RANGE') || headers.has('LUT_3D_INPUT_RANGE')) &&
		(headers.has('DOMAIN_MIN') ||
			headers.has('DOMAIN_MAX') ||
			headers.has(type === '1d' ? 'LUT_3D_INPUT_RANGE' : 'LUT_1D_INPUT_RANGE'))
	) {
		throw new Error('Conflicting LUT input range headers.');
	}

	return {type, size, title, domainMin, domainMax, data};
};

export const applyCubeLut = (pixels: Uint8ClampedArray, lut: CubeLut): void => {
	const {data, size, domainMin, domainMax, type} = lut;
	const last = size - 1;
	const range = domainMin.map((min, channel) => domainMax[channel] - min);

View on GitHub (pinned to 46a3a6bf13)