{"record":{"id":"9592f51d9ff1fa9a","repo":"remotion-dev/remotion","slug":"name-must-be-one-of-variants-join","errorCode":null,"errorMessage":"\"${name}\" must be one of ${variants.join(', ')}","messagePattern":"\"(.+?)\" must be one of (.+?)","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/brand/src/effects/metallic-swirl-effect.ts","lineNumber":306,"sourceCode":"\tmin: number,\n\tmax: number,\n): void => {\n\tif (value < min || value > max) {\n\t\tthrow new TypeError(`\"${name}\" must be between ${min} and ${max}`);\n\t}\n};\n\nconst assertOptionalEnum = <T extends string>(\n\tvalue: unknown,\n\tname: keyof MetallicSwirlParams,\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 one of ${variants.join(', ')}`);\n\t}\n};\n\nconst parseHexColor = (hex: string, name: keyof MetallicSwirlParams): Rgb => {\n\tconst match = /^#?([a-f\\d]{2})([a-f\\d]{2})([a-f\\d]{2})$/i.exec(hex);\n\tif (!match) {\n\t\tthrow new TypeError(`\"${name}\" must be a hex color such as \"#000000\"`);\n\t}\n\n\treturn [\n\t\tparseInt(match[1], 16) / 255,\n\t\tparseInt(match[2], 16) / 255,\n\t\tparseInt(match[3], 16) / 255,\n\t];\n};\n\nconst validateMetallicSwirlParams = (\n\tparams: MetallicSwirlParams = {},","sourceCodeStart":288,"sourceCodeEnd":324,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/brand/src/effects/metallic-swirl-effect.ts#L288-L324","documentation":"`assertOptionalEnum` checks the `mode` field against `MODES = ['blend', 'alpha-mask']`. `undefined` is allowed (defaults to 'blend'), but any non-string or any string not in the variants throws. The message lists the valid variants.","triggerScenarios":"`metallicSwirl({mode: 'normal'})`, `metallicSwirl({mode: 'BLEND'})` (case-sensitive), `metallicSwirl({mode: 1})` (number), `metallicSwirl({mode: null})`.","commonSituations":"Typo in a config file; case mismatch from user input; passing a numeric index instead of the string name; copy-paste from a different effect's mode names.","solutions":["Use exactly one of the listed variants: `'blend'` or `'alpha-mask'`.","Normalize user input to lowercase and validate against the list before passing.","Omit `mode` entirely if you want the default (`'blend'`).","Type the field as `MetallicSwirlMode` so invalid literals are rejected at compile time."],"exampleFix":"// before\nmetallicSwirl({mode: 'BLEND'}); // wrong case\n\n// after\nmetallicSwirl({mode: 'blend'});","handlingStrategy":"type-guard","validationCode":"// Validate the mode enum before passing.\nconst MODES = ['blend', 'alpha-mask'] as const;\ntype MetallicSwirlMode = (typeof MODES)[number];\n\nconst asMode = (v: unknown): MetallicSwirlMode | undefined => {\n  if (v === undefined) return undefined;\n  if (typeof v === 'string' && (MODES as readonly string[]).includes(v)) {\n    return v as MetallicSwirlMode;\n  }\n  throw new Error(`mode must be one of ${MODES.join(', ')}`);\n};\nmetallicSwirl({mode: asMode(raw.mode)});","typeGuard":"const isMetallicSwirlMode = (v: unknown): v is MetallicSwirlMode =>\n  typeof v === 'string' && (MODES as readonly string[]).includes(v);","tryCatchPattern":null,"preventionTips":["Lowercase user input and validate against the modes list before passing.","Omit `mode` to use the default ('blend') instead of passing a guess.","Type the field as `MetallicSwirlMode` so invalid literals fail at compile time.","Keep a single source of truth for the mode list in your config UI."],"tags":["brand","metallic-swirl","validation","params","enum"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}