{"record":{"id":"da4c9d3ac2097501","repo":"remotion-dev/remotion","slug":"name-must-be-formatenum-variants","errorCode":null,"errorMessage":"\"${name}\" must be ${formatEnum(variants)}","messagePattern":"\"(.+?)\" must be (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/effects/src/halftone-linear-gradient.ts","lineNumber":172,"sourceCode":"\t}\n\n\treturn `${variants\n\t\t.slice(0, -1)\n\t\t.map((variant) => `\"${variant}\"`)\n\t\t.join(', ')} or \"${variants[variants.length - 1]}\"`;\n};\n\nconst assertOptionalEnum = <T extends string>(\n\tvalue: unknown,\n\tname: string,\n\tvariants: readonly T[],\n): void => {\n\tif (value === undefined) {\n\t\treturn;\n\t}\n\n\tif (typeof value !== 'string' || !variants.includes(value as T)) {\n\t\tthrow new TypeError(`\"${name}\" must be ${formatEnum(variants)}`);\n\t}\n};\n\nconst resolve = (\n\tp: HalftoneLinearGradientParams,\n): HalftoneLinearGradientResolved => ({\n\tfirstStopDotSize: p.firstStopDotSize ?? DEFAULT_FIRST_STOP_DOT_SIZE,\n\tsecondStopDotSize: p.secondStopDotSize ?? DEFAULT_SECOND_STOP_DOT_SIZE,\n\tfirstStopPosition: [\n\t\t...(p.firstStopPosition ?? DEFAULT_FIRST_STOP_POSITION),\n\t] as UvCoordinate,\n\tsecondStopPosition: [\n\t\t...(p.secondStopPosition ?? DEFAULT_SECOND_STOP_POSITION),\n\t] as UvCoordinate,\n\tgridSize: p.gridSize ?? DEFAULT_GRID_SIZE,\n\tcolorMode: p.colorMode ?? 'solid',\n\tdotColor:\n\t\t'dotColor' in p ? (p.dotColor ?? DEFAULT_DOT_COLOR) : DEFAULT_DOT_COLOR,","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/effects/src/halftone-linear-gradient.ts#L154-L190","documentation":"TypeError thrown by halftone-linear-gradient's assertOptionalEnum (halftone-linear-gradient.ts:162) when colorMode is provided but is not one of the allowed variants. Allowed variants are HALFTONE_LINEAR_GRADIENT_COLOR_MODES ('solid' or 'source'). The message lists the valid choices via formatEnum.","triggerScenarios":"validateHalftoneLinearGradientParams calls assertOptionalEnum(params.colorMode, 'colorMode', HALFTONE_LINEAR_GRADIENT_COLOR_MODES) (line 234). Triggered by passing colorMode: 'custom', colorMode: '', or any string other than 'solid'/'source'. A non-string colorMode (e.g. a number) also triggers.","commonSituations":"Typo in colorMode; copying a value from a different effect's API; passing a value derived from user input without narrowing; assuming an enum that no longer matches after a version upgrade.","solutions":["Set colorMode to 'solid' (use dotColor) or 'source' (sample source colors).","If accepting user input, narrow it before passing: ['solid','source'].includes(v) ? v : 'solid'.","Check the effect's docs/types for the current enum after upgrading @remotion/effects."],"exampleFix":"// before\n<halftoneLinearGradient colorMode=\"colored\" />\n// -> \"colorMode\" must be \"solid\" or \"source\"\n\n// after\n<halftoneLinearGradient colorMode=\"solid\" dotColor=\"#ff00aa\" />","handlingStrategy":"type-guard","validationCode":"const COLOR_MODES = ['solid', 'source'] as const;\ntype ColorMode = typeof COLOR_MODES[number];\nconst normalizeColorMode = (v: unknown): ColorMode =>\n  COLOR_MODES.includes(v as ColorMode) ? (v as ColorMode) : 'solid';","typeGuard":"const isColorMode = (v: unknown): v is 'solid' | 'source' =>\n  v === 'solid' || v === 'source';","tryCatchPattern":"null","preventionTips":["Narrow user input to the enum before passing it.","Reference the effect's exported enum/types rather than string literals.","After upgrading @remotion/effects, recheck the allowed colorMode values.","Let TypeScript's union type catch typos at compile time."],"tags":["halftone-linear-gradient-effect","validation","typescript","enum","params"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}