remotion-dev/remotion · error · TypeError

"palette" must be an array with at least 2 colors, but got $

Error message

"palette" must be an array with at least 2 colors, but got ${JSON.stringify(palette)}

What it means

The thermal vision effect's optional `palette` parameter must be an array containing at least 2 color strings. This TypeError is thrown by `validatePalette` (called from `validateThermalVisionParams`) when `palette` is defined but is not an array or has fewer than 2 entries. Note `undefined` is allowed (defaults to an 8-color ramp); only a present-but-invalid value triggers this.

Source

Thrown at packages/effects/src/thermal-vision.ts:84

		readonly uPaletteLength: WebGLUniformLocation | null;
		readonly uAmount: WebGLUniformLocation | null;
	};
	cachedPaletteKey: string;
	palettePixelData: Uint8Array;
};

const resolve = (p: ThermalVisionParams): ThermalVisionResolved => ({
	amount: p.amount ?? DEFAULT_AMOUNT,
	palette: p.palette ?? DEFAULT_PALETTE,
});

const validatePalette = (palette: unknown): void => {
	if (palette === undefined) {
		return;
	}

	if (!Array.isArray(palette) || palette.length < 2) {
		throw new TypeError(
			`"palette" must be an array with at least 2 colors, but got ${JSON.stringify(palette)}`,
		);
	}

	for (let i = 0; i < palette.length; i++) {
		assertRequiredColor(palette[i], `palette[${i}]`);
	}
};

const validateThermalVisionParams = (params: ThermalVisionParams): void => {
	assertEffectParamsObject(params, 'Thermal vision');
	assertOptionalFiniteNumber(params.amount, 'amount');
	validatePalette(params.palette);

	const {amount} = resolve(params);
	validateUnitInterval(amount, 'amount');
};

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Provide an array of at least 2 valid color strings, e.g. `palette: ['#0000ff', '#ff0000']`.
  2. Omit `palette` to use the built-in default 8-color thermal ramp.
  3. If loading palette from external config, validate its length >= 2 before passing.

Example fix

// before
thermalVision({palette: ['#0000ff']});
// after
thermalVision({palette: ['#0000ff', '#00ff00', '#ff0000']});
Defensive patterns

Strategy: validation

Validate before calling

const isValidPalette = (p: unknown): p is readonly string[] =>
  Array.isArray(p) && p.length >= 2 && p.every((c) => typeof c === 'string');

const palette = loadPaletteFromConfig();
if (palette !== undefined && !isValidPalette(palette)) {
  throw new Error('palette must have >= 2 colors');
}
thermalVision({palette});

Type guard

const isThermalPalette = (v: unknown): v is readonly string[] =>
  Array.isArray(v) && v.length >= 2 && v.every((c) => typeof c === 'string');

Try / catch

try {
  thermalVision({...params});
} catch (e) {
  if (e instanceof TypeError && /palette.*at least 2/.test(e.message)) {
    thermalVision({...params, palette: undefined}); // use default ramp
  } else throw e;
}

Prevention

When it happens

Trigger: Passing `palette` as a non-array (e.g. `palette: '#ff0000'`), an empty array (`palette: []`), or a single-element array (`palette: ['#ff0000']`). Each element is then separately validated as a color by `assertRequiredColor`.

Common situations: Passing a single hex string instead of an array; deserializing a palette from config that was truncated; misunderstanding that at least two colors are needed to form a ramp; accidental `palette: null`.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/263f73d8e9e999f9. Report an issue: GitHub.