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

Thrown by the evolve effect's assertOptionalEnum() (a TypeError) when a `direction` value is supplied but is not one of the four allowed variants 'left' | 'right' | 'top' | 'bottom'. The check is skipped when direction is undefined (the default 'left' applies), so it only fires for a present-but-invalid string. The message lists the allowed variants via formatEnum().

Source

Thrown at packages/effects/src/evolve.ts:87

	}

	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: EvolveParams): EvolveResolved => ({
	progress: p.progress ?? DEFAULT_PROGRESS,
	direction: p.direction ?? DEFAULT_DIRECTION,
	feather: p.feather ?? DEFAULT_FEATHER,
});

const validateEvolveParams = (params: EvolveParams): void => {
	assertEffectParamsObject(params, 'Evolve');
	assertOptionalFiniteNumber(params.progress, 'progress');
	assertOptionalFiniteNumber(params.feather, 'feather');
	assertOptionalEnum(params.direction, 'direction', EVOLVE_DIRECTIONS);

	const r = resolve(params);

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Use one of the exact lowercase literals: 'left', 'right', 'top', or 'bottom'.
  2. Type the prop against the exported EvolveDirection type so the compiler rejects invalid values.
  3. If the direction comes from data, validate/match it against the allowed list before passing it in.
  4. Omit direction to accept the default 'left'.

Example fix

// before
evolve({progress: 0.5, direction: 'Left'})

// after
import {type EvolveDirection} from '@remotion/effects';
evolve({progress: 0.5, direction: 'left'})
Defensive patterns

Strategy: validation

Validate before calling

import {type EvolveDirection} from '@remotion/effects';

const EVOLVE_DIRECTIONS = ['left', 'right', 'top', 'bottom'] as const;

function normalizeDirection(value: string): EvolveDirection | null {
  const match = EVOLVE_DIRECTIONS.find((d) => d === value.toLowerCase());
  return match ?? null;
}

// Validate before calling evolve():
const dir = normalizeDirection(userInput);
if (!dir) throw new TypeError(`invalid direction: ${userInput}`);
evolve({direction: dir});

Type guard

import {type EvolveDirection} from '@remotion/effects';

const EVOLVE_DIRECTIONS = ['left', 'right', 'top', 'bottom'] as const;

function isEvolveDirection(v: unknown): v is EvolveDirection {
  return typeof v === 'string' &&
    (EVOLVE_DIRECTIONS as readonly string[]).includes(v);
}

Prevention

When it happens

Trigger: Calling evolve({direction: 'Left'}), evolve({direction: 'CENTER'}), evolve({direction: 'up'}), or any other string outside the four literals. Common with case mismatches or typos.

Common situations: Wrong letter casing (the variants are lowercase), a typo, or a dynamically constructed direction string that does not match a variant exactly.

Related errors


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