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 in the Lines effect when the colors parameter is present but is not an array, or is an array with fewer than 2 entries. The Lines effect cycles stripe colors and needs at least two to form a pattern; undefined is allowed (it falls back to default light-blue shades), but any other non-array value or a 0/1-element array is rejected.

Source

Thrown at packages/effects/src/lines.ts:186

		);
	}
};

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' ||
		!LINE_DIRECTIONS.includes(direction as LinesDirection)
	) {

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Pass an array of at least two color strings, e.g. lines({ colors: ['#dff4ff', '#7cc6ff'] }).
  2. Omit colors entirely to use the built-in defaults.
  3. When building colors dynamically, guard with if (colors.length >= 2) or append a fallback color.

Example fix

// before
lines({ colors: [primaryColor] })

// after
lines({ colors: [primaryColor, primaryColor] })
// or
lines({}) // use defaults
Defensive patterns

Strategy: validation

Validate before calling

function safeColors(c: unknown): readonly string[] | undefined {
  if (c === undefined) return undefined;
  if (!Array.isArray(c) || c.length < 2) return undefined; // or throw your own
  return c.filter((x) => typeof x === 'string' && x.length > 0);
}
lines({ colors: safeColors(userColors) });

Type guard

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

Prevention

When it happens

Trigger: Calling lines({ colors: ['#fff'] }) (single color), lines({ colors: 'red' }) (string not array), lines({ colors: [] }) (empty), or lines({ colors: null }). Each element is also validated as a non-empty string by assertRequiredColor.

Common situations: Passing a single hex string instead of an array; dynamically building the colors array from data that yields one item; spreading a possibly-empty array.

Related errors


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