remotion-dev/remotion · error · TypeError

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

Error message

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

What it means

Thrown by validateColors() during waves() effect param validation. The waves effect requires the colors array to have at least 2 entries (the stripe pattern alternates between colors). This TypeError fires when colors is not an array, is an empty array, or has only one element. The error includes the received value via JSON.stringify for diagnostics.

Source

Thrown at packages/effects/src/waves.ts:231

		);
	}
};

const validateNonNegative = (value: number, name: string): void => {
	if (value < 0) {
		throw new TypeError(
			`"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}`,
		);
	}
};

const validateColors = (colors: unknown): void => {
	if (colors === undefined) {
		return;
	}

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

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

const validateDirection = (direction: unknown): void => {
	if (direction === undefined) {
		return;
	}

	if (
		typeof direction !== 'string' ||
		!WAVE_DIRECTIONS.includes(direction as WavesDirection)
	) {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Provide at least two colors: waves({colors: ['#fff', '#000']}).
  2. If your data has fewer than 2 colors, pad it or fall back to the default by omitting the colors param.
  3. If you want a single-color effect, use a different effect (e.g., a solid overlay) rather than waves().
  4. Validate the array length in your own code before passing it: colors.length >= 2 ? colors : undefined.

Example fix

// before
import {waves} from '@remotion/effects';
waves({colors: ['#ff0000']})   // throws — only 1 color
waves({colors: []})             // throws — empty
waves({colors: 'red'})          // throws — not an array

// after
waves({colors: ['#ff0000', '#00ff00']})  // valid — 2 colors
waves({colors: palette.length >= 2 ? palette : undefined})  // fall back to default
Defensive patterns

Strategy: validation

Validate before calling

import type {WavesParams} from '@remotion/effects';

const safeColors = (colors: WavesParams['colors']): readonly string[] | undefined => {
  if (colors === undefined) return undefined;
  if (!Array.isArray(colors) || colors.length < 2) {
    // Fall back to default rather than throw
    return undefined;
  }
  return colors;
};

const colors = safeColors(myColors);
waves({colors});

Type guard

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

Prevention

When it happens

Trigger: Called from validateWavesParams() at packages/effects/src/waves.ts:258 via validateColors(params.colors). Fires when you pass waves({colors: []}), waves({colors: ['#fff']}), or waves({colors: 'red'}). If colors is omitted entirely (undefined), the default ['#dff4ff', '#7cc6ff'] is used and no error is thrown.

Common situations: Passing a single-element color array expecting a solid color (the effect needs at least two to form stripes); passing colors as a string instead of an array; dynamically generating the colors array from data that happens to have one entry; accidentally spreading an empty array.

Related errors


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