remotion-dev/remotion · error · TypeError

"invert" must be a boolean, but got ${JSON.stringify(params.

Error message

"invert" must be a boolean, but got ${JSON.stringify(params.invert)}

What it means

The mirror() effect's optional `invert` prop controls which side of the image is mirrored. validateMirrorParams throws this TypeError when `invert` is provided (not undefined) but is not a JavaScript boolean. The TypeScript type MirrorParams marks invert as `boolean | undefined`, so this fires only when runtime values bypass type checking — e.g. deserialized JSON, URL params, or form inputs that produce strings/numbers.

Source

Thrown at packages/effects/src/mirror/index.ts:82

	invert: p.invert ?? false,
});

const validateMirrorParams = (params: MirrorParams): void => {
	assertEffectParamsObject(params, 'Mirror');
	assertOptionalFiniteNumber(params.position, 'position');

	if (
		params.direction !== undefined &&
		params.direction !== 'horizontal' &&
		params.direction !== 'vertical'
	) {
		throw new TypeError(
			`"direction" must be "horizontal" or "vertical", but got ${JSON.stringify(params.direction)}`,
		);
	}

	if (params.invert !== undefined && typeof params.invert !== 'boolean') {
		throw new TypeError(
			`"invert" must be a boolean, but got ${JSON.stringify(params.invert)}`,
		);
	}

	const {position} = resolve(params);
	validateUnitInterval(position, 'position');
};

export const mirror = createEffect<MirrorParams, MirrorState>({
	type: 'dev.remotion.effects.mirror',
	label: 'mirror()',
	documentationLink: 'https://www.remotion.dev/docs/effects/mirror',
	backend: 'webgl2',
	calculateKey: (params) => {
		const r = resolve(params);
		return `mirror-${r.direction}-${r.position}-${r.invert ? 1 : 0}`;
	},
	setup: (target) => setupMirror(target),

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Ensure invert is a native JavaScript boolean — mirror({ invert: true }) or mirror({ invert: false }) — not a string or number.
  2. If the value comes from JSON or a URL param, coerce explicitly: mirror({ invert: value === true || value === 'true' }).
  3. Omit invert entirely if you want the default (false): mirror({ direction: 'horizontal' }).
  4. Check the upstream source of the value — DOM inputs and URLSearchParams always return strings.

Example fix

// before
mirror({ invert: 'true' })
mirror({ invert: 1 })

// after
mirror({ invert: true })
mirror({ invert: Boolean(parsedValue) })
Defensive patterns

Strategy: validation

Validate before calling

// Before calling mirror(), verify invert is a boolean or undefined
if (params.invert !== undefined && typeof params.invert !== 'boolean') {
  throw new Error(`invert must be a boolean, got ${typeof params.invert}`);
}
const result = mirror(params);

Type guard

const isMirrorParams = (p: unknown): p is MirrorParams => {
  if (typeof p !== 'object' || p === null) return false;
  const obj = p as Record<string, unknown>;
  if (obj.invert !== undefined && typeof obj.invert !== 'boolean') return false;
  return true;
};

Prevention

When it happens

Trigger: Calling mirror({ invert: 'true' }) (string), mirror({ invert: 1 }) (number), mirror({ invert: null }), or mirror({ invert: 'false' }). Any value that is not literally `true` or `false` and not `undefined` triggers it.

Common situations: Loading effect parameters from a JSON config file or localStorage where booleans serialize to strings; reading values from HTML form inputs (which always yield strings); passing query-string parameters; dynamic interpolation that produces non-boolean results.

Related errors


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