remotion-dev/remotion · error

"content" must be a non-empty string, but got

Error message

"content" must be a non-empty string, but got ${JSON.stringify(params.content)}

What it means

validateLutParams requires params.content to be a non-empty (after trim) string containing the inline text of a .cube 3D LUT file. This TypeError is thrown when content is missing, not a string (number, object, null, undefined) or only whitespace. After this check, the content is also parsed via getCachedLut, so syntactically invalid .cube content will fail later in parseCubeLut.

Solutions

  1. Pass the actual text contents of the .cube file as a string: lut({content: fileText}).
  2. If loading from a URL or file, await the read: const content = await response.text(); then validate content.trim().length > 0 before calling lut().
  3. Verify the property is named `content`, matching the LutParams type.
  4. Type the input as LutParams so TypeScript catches missing/incorrect content at compile time.

Example fix

// before
const effect = lut({content: await fetch(url)});
// after
const content = await (await fetch(url)).text();
if (content.trim().length === 0) throw new Error('LUT file is empty');
const effect = lut({content});
Defensive patterns

Strategy: validation

Validate before calling

const content = typeof raw === 'string' ? raw : null;
if (!content || content.trim().length === 0) {
  throw new Error('LUT content must be a non-empty .cube text string');
}
lut({content});

Type guard

const hasLutContent = (p: unknown): p is {content: string} =>
  typeof p === 'object' && p !== null &&
  typeof (p as {content?: unknown}).content === 'string' &&
  (p as {content: string}).content.trim().length > 0;

Try / catch

try {
  const effect = lut({content});
} catch (e) {
  if (e instanceof TypeError && e.message.includes('"content" must be a non-empty string')) {
    console.error('The .cube file text was empty or not a string');
  } else throw e;
}

Prevention

When it happens

Trigger: `lut({})`, `lut({content: undefined})`, `lut({content: 42})`, `lut({content: ' '})`, or a typo like `lut({text: '...'})` (wrong property name yields content: undefined).

Common situations: Fetching a .cube file and passing the File/Blob object instead of its text; using the wrong property name; forgetting to await fs.readFile/text() so a Promise or undefined is passed; an empty file served from a URL.

Understand the failure class

Background: "must not be empty", "cannot be empty" — required-field validation errors across open-source libraries — 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/c9f37971f24cc6c6. Report an issue: GitHub.

Appendix: source

Thrown at packages/effects/src/lut/index.ts:87

			parsedLuts.delete(oldestContent);
		}
	}

	return created;
};

const validateLutParams = (params: LutParams): void => {
	if (params === null || typeof params !== 'object') {
		throw new TypeError(
			`LUT effect requires a parameters object, but got ${JSON.stringify(params)}`,
		);
	}

	if (
		typeof params.content !== 'string' ||
		params.content.trim().length === 0
	) {
		throw new TypeError(
			`"content" must be a non-empty string, but got ${JSON.stringify(params.content)}`,
		);
	}

	getCachedLut(params.content);
};

export const lut = createEffect<LutParams, LutState>({
	type: 'remotion/lut',
	label: 'lut()',
	documentationLink: 'https://www.remotion.dev/docs/effects/lut',
	backend: 'webgl2',
	calculateKey: (params) => getCachedLut(params.content).effectKey,
	setup: setupLut,
	apply: ({source, width, height, params, state, flipSourceY}) => {
		applyLut({
			state,
			source,

View on GitHub (pinned to 46a3a6bf13)