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
- Pass an array of at least two color strings, e.g. lines({ colors: ['#dff4ff', '#7cc6ff'] }).
- Omit colors entirely to use the built-in defaults.
- 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
- Always pass at least two color strings, or omit colors to use defaults.
- When building colors from data, guard length and append a fallback before calling lines().
- Remember each element is also checked for being a non-empty string.
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
- "colors" must be an array with at least 2 colors, but got ${
- "${name}" must be greater than or equal to 0, but got ${JSON
- "direction" must be ${formatEnum(LINE_DIRECTIONS)}, but got
- "colors" must be an array with at least 2 colors, but got ${
- "${name}" must be greater than 0, but got ${JSON.stringify(v
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/3d53b794100d5b9e.
Report an issue: GitHub.