remotion-dev/remotion · error · TypeError

"direction" must be ${formatEnum(ZIGZAG_DIRECTIONS)}, but go

Error message

"direction" must be ${formatEnum(ZIGZAG_DIRECTIONS)}, but got ${JSON.stringify(direction)}

What it means

Zigzag's direction must be one of the ZIGZAG_DIRECTIONS enum ('horizontal' or 'vertical'); validateDirection throws a TypeError for anything else (undefined is allowed and defaults to 'horizontal'). The check uses Array.includes on the const tuple, so typos, wrong case, or non-string values are rejected.

Source

Thrown at packages/effects/src/zigzag.ts:235

			`"colors" must be an array with at least 2 colors, but got ${JSON.stringify(colors)}`,
		);
	}

	for (let i = 0; i < colors.length; i++) {
		assertRequiredColor(colors[i], `colors[${i}]`);
	}
};

const validateDirection = (direction: unknown): void => {
	if (direction === undefined) {
		return;
	}

	if (
		typeof direction !== 'string' ||
		!ZIGZAG_DIRECTIONS.includes(direction as ZigzagDirection)
	) {
		throw new TypeError(
			`"direction" must be ${formatEnum(ZIGZAG_DIRECTIONS)}, but got ${JSON.stringify(direction)}`,
		);
	}
};

const validateZigzagParams = (params: ZigzagParams): void => {
	assertEffectParamsObject(params, 'Zigzag');
	validateColors(params.colors);
	validateDirection(params.direction);
	assertOptionalFiniteNumber(params.thickness, 'thickness');
	assertOptionalFiniteNumber(params.gap, 'gap');
	assertOptionalFiniteNumber(params.angle, 'angle');
	assertOptionalFiniteNumber(params.offset, 'offset');
	assertOptionalFiniteNumber(params.amplitude, 'amplitude');
	assertOptionalFiniteNumber(params.wavelength, 'wavelength');
	assertOptionalBoolean(params.maskToSourceAlpha, 'maskToSourceAlpha');

	const thickness = params.thickness ?? DEFAULT_THICKNESS;

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Use exactly 'horizontal' or 'vertical' (lowercase).
  2. Omit direction to get the 'horizontal' default.
  3. If the value comes from user/config input, constrain it with a union type or validate against ['horizontal','vertical'] first.

Example fix

// before
zigzag({direction: 'h'});
zigzag({direction: 'Vertical'});

// after
zigzag({direction: 'horizontal'});
zigzag({direction: 'vertical'});
Defensive patterns

Strategy: type-guard

Validate before calling

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

const ZIGZAG_DIRECTIONS = ['horizontal', 'vertical'] as const;
type Dir = (typeof ZIGZAG_DIRECTIONS)[number];

const dir: unknown = config.direction;
const safeDir = (typeof dir === 'string' && (ZIGZAG_DIRECTIONS as readonly string[]).includes(dir))
  ? (dir as Dir)
  : undefined; // let default 'horizontal' apply

zigzag({direction: safeDir});

Type guard

const ZIGZAG_DIRECTIONS = ['horizontal', 'vertical'] as const;
type ZigzagDirection = (typeof ZIGZAG_DIRECTIONS)[number];

const isZigzagDirection = (v: unknown): v is ZigzagDirection =>
  typeof v === 'string' && (ZIGZAG_DIRECTIONS as readonly string[]).includes(v);

// usage:
zigzag({direction: isZigzagDirection(dir) ? dir : undefined});

Try / catch

try {
  return <VideoEffects effects={[zigzag({direction})]} />;
} catch (err) {
  if (err instanceof TypeError && /"direction" must be/.test(err.message)) {
    return <VideoEffects effects={[zigzag({direction: 'horizontal'})]} />;
  }
  throw err;
}

Prevention

When it happens

Trigger: Calling zigzag({direction: 'h'}), zigzag({direction: 'Horizontal'}), zigzag({direction: 'diagonal'}), zigzag({direction: 0}), or zigzag({direction: null}).

Common situations: Abbreviating the value; using wrong casing; copying a value from a different effect's enum; passing a numeric index expecting it to map.

Related errors


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