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
Zigzag requires a colors array with at least two entries (it samples a 1-D palette texture indexed by stripe position, so a single color is meaningless). validateColors throws a TypeError if colors is omitted-but-not-undefined, not an array, or has fewer than two elements; each entry must then pass assertRequiredColor (a non-empty string). Note undefined is allowed because colors defaults to ['#dff4ff','#7cc6ff'].
Source
Thrown at packages/effects/src/zigzag.ts:216
);
}
};
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' ||
!ZIGZAG_DIRECTIONS.includes(direction as ZigzagDirection)
) {View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Always provide at least two color strings: zigzag({colors: ['#ff0000', '#00ff00']}).
- If building the list dynamically, guard length before passing: colors.length >= 2 ? colors : undefined (lets the default apply).
- Ensure each entry is a parseable CSS color string, not an object or empty string.
Example fix
// before
zigzag({colors: []}); // throws
zigzag({colors: ['#ff0000']}); // throws
zigzag({colors: '#ff0000'}); // throws
// after
zigzag({colors: ['#ff0000', '#00ff00']});
zigzag({colors: list.length >= 2 ? list : undefined}); Defensive patterns
Strategy: type-guard
Validate before calling
import {zigzag} from '@remotion/effects';
const colors = userInputColors; // unknown shape
if (!Array.isArray(colors) || colors.length < 2 ||
!colors.every((c) => typeof c === 'string' && c.length > 0)) {
// fall back to default palette by omitting colors
zigzag({});
} else {
zigzag({colors: colors as [string, string, ...string[]]});
} Type guard
const isZigzagColors = (v: unknown): v is [string, string, ...string[]] =>
Array.isArray(v) &&
v.length >= 2 &&
v.every((c) => typeof c === 'string' && c.length > 0);
// usage:
zigzag({colors: isZigzagColors(colors) ? colors : undefined}); Try / catch
try {
return <VideoEffects effects={[zigzag({colors})]} />;
} catch (err) {
if (err instanceof TypeError && /colors.*array with at least 2/.test(err.message)) {
return <VideoEffects effects={[zigzag({colors: ['#dff4ff', '#7cc6ff']})]} />;
}
throw err;
} Prevention
- Always pass at least two parseable CSS color strings in colors.
- When colors come from dynamic data, guard length and element type, or pass undefined to use the default palette.
- Do not pass a single-element array, a bare string, or null.
When it happens
Trigger: Calling zigzag({colors: []}), zigzag({colors: ['#ff0000']}), zigzag({colors: null}), zigzag({colors: 'red'}), or zigzag({colors: 42}).
Common situations: Passing a single-color array expecting a solid fill; passing a CSS color string instead of an array; spreading a possibly-empty list; setting colors from data that may contain one item.
Related errors
- "${name}" must be greater than 0, but got ${JSON.stringify(v
- "${name}" must be greater than or equal to 0, but got ${JSON
- "direction" must be ${formatEnum(ZIGZAG_DIRECTIONS)}, but go
- loadFont() requires an object as its argument, but received
- loadFont() requires a "url" field in the options object, but
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/c16940889e22229c.
Report an issue: GitHub.