remotion-dev/remotion · error · TypeError

"${name}" must be ${formatEnum(variants)}, but got ${JSON.st

Error message

"${name}" must be ${formatEnum(variants)}, but got ${JSON.stringify(value)}

What it means

TypeError thrown by vignette's assertOptionalEnum when params.mode is defined but is not one of the allowed VIGNETTE_MODES ("color" or "alpha"). Validation runs synchronously when vignette() is called; the offending value is echoed via JSON.stringify so you can see exactly what was rejected.

Source

Thrown at packages/effects/src/vignette.ts:158

	}

	return `${variants
		.slice(0, -1)
		.map((variant) => `"${variant}"`)
		.join(', ')} or "${variants[variants.length - 1]}"`;
};

const assertOptionalEnum = <T extends string>(
	value: unknown,
	name: string,
	variants: readonly T[],
): void => {
	if (value === undefined) {
		return;
	}

	if (!variants.includes(value as T)) {
		throw new TypeError(
			`"${name}" must be ${formatEnum(variants)}, but got ${JSON.stringify(value)}`,
		);
	}
};

const resolve = (p: VignetteParams): VignetteResolved => ({
	amount: p.amount ?? DEFAULT_AMOUNT,
	radius: p.radius ?? DEFAULT_RADIUS,
	feather: p.feather ?? DEFAULT_FEATHER,
	roundness: p.roundness ?? DEFAULT_ROUNDNESS,
	color: p.color ?? DEFAULT_COLOR,
	mode: p.mode ?? DEFAULT_MODE,
	center: [...(p.center ?? DEFAULT_CENTER)] as VignetteCenter,
});

const assertOptionalUvCoordinate = (value: unknown, name: string): void => {
	if (value === undefined) {
		return;

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Use exactly "color" or "alpha", or omit mode to accept the default.
  2. If the value is dynamic, validate it against ['color','alpha'] before passing it.
  3. Search the codebase for the misspelled value and correct the source.
  4. Add a TypeScript literal union for mode so the compiler rejects invalid values at build time.

Example fix

// before
import {vignette} from '@remotion/effects';

const e = vignette({mode: 'Colour', amount: 0.6}); // throws TypeError

// after
const e = vignette({mode: 'color', amount: 0.6});
// or omit for the default
const e2 = vignette({amount: 0.6});
Defensive patterns

Strategy: validation

Validate before calling

import {vignette} from '@remotion/effects';

const VIGNETTE_MODES = ['color', 'alpha'] as const;
type VignetteMode = (typeof VIGNETTE_MODES)[number];

const assertMode = (mode: unknown): VignetteMode | undefined => {
  if (mode === undefined) return undefined;
  if (!VIGNETTE_MODES.includes(mode as VignetteMode)) {
    throw new TypeError(`mode must be one of ${VIGNETTE_MODES.join('|')}, got ${JSON.stringify(mode)}`);
  }
  return mode as VignetteMode;
};

const mode = assertMode(config.mode); // throws before vignette() is called
const e = vignette({mode, amount: 0.6});

Type guard

const VIGNETTE_MODES = ['color', 'alpha'] as const;
type VignetteMode = (typeof VIGNETTE_MODES)[number];
const isVignetteMode = (v: unknown): v is VignetteMode =>
  typeof v === 'string' && (VIGNETTE_MODES as readonly string[]).includes(v);

Try / catch

try {
  const e = vignette({mode: config.mode, amount: 0.6});
} catch (err) {
  if (err instanceof TypeError) {
    console.error('Invalid vignette mode:', config.mode, err);
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling vignette({mode: 'Colour'}) (wrong case), vignette({mode: 'soft'}), vignette({mode: 1}), or passing a variable holding an unexpected string. The check is skipped only when mode is undefined (defaults apply).

Common situations: Case typos ("Color", "COLOR"); copying a mode name from another library; data-driven mode values coming from an API or config without validation; renaming the variant and missing a call site.

Related errors


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/1ac4030ebbf89253. Report an issue: GitHub.