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 the `rings()` effect when `colors` is supplied but is not an array, or is an array with fewer than 2 entries. The effect cycles colors across concentric rings, so a single color would make every ring identical and is treated as a configuration error. `undefined` is allowed (defaults to `['#dff4ff', '#7cc6ff']`); only a present-but-invalid value throws.

Source

Thrown at packages/effects/src/rings.ts:162

		);
	}
};

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 assertOptionalCenter = (value: unknown, name: string): void => {
	if (value === undefined) {
		return;
	}

	if (
		!Array.isArray(value) ||
		value.length !== 2 ||
		value.some((item) => typeof item !== 'number' || !Number.isFinite(item))

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Provide at least two color strings, e.g. `colors: ['#dff4ff', '#7cc6ff']`.
  2. Omit `colors` entirely to accept the default two-color palette.
  3. When building the array dynamically, guard with `if (palette.length >= 2) rings({colors: palette}); else rings({});`.

Example fix

// before
rings({colors: data.map((d) => d.color)});
// after
const palette = data.map((d) => d.color);
rings({colors: palette.length >= 2 ? palette : undefined});
Defensive patterns

Strategy: validation

Validate before calling

const validateRingsColors = (colors: unknown): string[] | undefined => {
  if (colors === undefined) return undefined;
  if (!Array.isArray(colors) || colors.length < 2 ||
      colors.some((c) => typeof c !== 'string' || c.length === 0)) {
    throw new TypeError('colors must be an array of >= 2 non-empty strings');
  }
  return colors as string[];
};

rings({colors: validateRingsColors(maybeColors)});

Type guard

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

Prevention

When it happens

Trigger: Call `rings({colors: ['#dff4ff']})` (one entry), `rings({colors: []})`, `rings({colors: 'red'})`, or `rings({colors: ['#fff', '']})` (the empty string is later rejected by `assertRequiredColor`). Also hit when a dynamically-built palette array is filtered down to fewer than 2 items at runtime.

Common situations: Building the palette from data that may collapse to one element (e.g. `colors: data.map(d => d.color)` where `data` is short); spreading a user-supplied array without a length check; passing a CSS color string instead of an array of strings.

Related errors


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