{"record":{"id":"3d53b794100d5b9e","repo":"remotion-dev/remotion","slug":"colors-must-be-an-array-with-at-least-2-colors-3d53b7","errorCode":null,"errorMessage":"\"colors\" must be an array with at least 2 colors, but got ${JSON.stringify(colors)}","messagePattern":"\"colors\" must be an array with at least 2 colors, but got (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/effects/src/lines.ts","lineNumber":186,"sourceCode":"\t\t);\n\t}\n};\n\nconst validateNonNegative = (value: number, name: string): void => {\n\tif (value < 0) {\n\t\tthrow new TypeError(\n\t\t\t`\"${name}\" must be greater than or equal to 0, but got ${JSON.stringify(value)}`,\n\t\t);\n\t}\n};\n\nconst validateColors = (colors: unknown): void => {\n\tif (colors === undefined) {\n\t\treturn;\n\t}\n\n\tif (!Array.isArray(colors) || colors.length < 2) {\n\t\tthrow new TypeError(\n\t\t\t`\"colors\" must be an array with at least 2 colors, but got ${JSON.stringify(colors)}`,\n\t\t);\n\t}\n\n\tfor (let i = 0; i < colors.length; i++) {\n\t\tassertRequiredColor(colors[i], `colors[${i}]`);\n\t}\n};\n\nconst validateDirection = (direction: unknown): void => {\n\tif (direction === undefined) {\n\t\treturn;\n\t}\n\n\tif (\n\t\ttypeof direction !== 'string' ||\n\t\t!LINE_DIRECTIONS.includes(direction as LinesDirection)\n\t) {","sourceCodeStart":168,"sourceCodeEnd":204,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/lines.ts#L168-L204","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nlines({ colors: [primaryColor] })\n\n// after\nlines({ colors: [primaryColor, primaryColor] })\n// or\nlines({}) // use defaults","handlingStrategy":"validation","validationCode":"function safeColors(c: unknown): readonly string[] | undefined {\n  if (c === undefined) return undefined;\n  if (!Array.isArray(c) || c.length < 2) return undefined; // or throw your own\n  return c.filter((x) => typeof x === 'string' && x.length > 0);\n}\nlines({ colors: safeColors(userColors) });","typeGuard":"const isColorArray = (v: unknown): v is readonly string[] =>\n  Array.isArray(v) &&\n  v.length >= 2 &&\n  v.every((x) => typeof x === 'string' && x.length > 0);","tryCatchPattern":null,"preventionTips":["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."],"tags":["validation","lines-effect","typescript","params","colors"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}