remotion-dev/remotion · error · TypeError
'preservePitch' must be a boolean or undefined but got '${ty
Error message
'preservePitch' must be a boolean or undefined but got '${typeof props.preservePitch}' instead What it means
The <Audio>, <Video>, <Html5Video>, and <Html5Audio> components accept a `preservePitch` boolean prop that controls whether the audio pitch is preserved when `playbackRate` is not 1 (it maps to the HTML5 media element's preservesPitch feature). validateMediaProps rejects any value that is not a boolean or undefined so the underlying media element always receives a well-typed flag. This guards against silent coercion bugs where a truthy non-boolean would behave unexpectedly.
Source
Thrown at packages/core/src/validate-media-props.ts:51
);
}
if (
typeof props.playbackRate === 'number' &&
(isNaN(props.playbackRate) ||
!Number.isFinite(props.playbackRate) ||
props.playbackRate <= 0)
) {
throw new TypeError(
`You have passed a playbackRate of ${props.playbackRate} to your <${component} /> component. Playback rate must be a real number above 0.`,
);
}
if (
typeof props.preservePitch !== 'boolean' &&
typeof props.preservePitch !== 'undefined'
) {
throw new TypeError(
`'preservePitch' must be a boolean or undefined but got '${typeof props.preservePitch}' instead`,
);
}
};
View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Pass preservePitch as a literal boolean or omit it: preservePitch={true} or preservePitch={false}.
- If the value comes from a string source, coerce explicitly before rendering: preservePitch={String(val).toLowerCase() === 'true'}.
- If the value comes from a number (0/1), convert: preservePitch={Boolean(numVal)}.
- Omit the prop entirely to accept the default (undefined, which lets the browser default apply).
Example fix
// before
<Video src={src} playbackRate={2} preservePitch="true" />
// after
<Video src={src} playbackRate={2} preservePitch={true} /> Defensive patterns
Strategy: type-guard
Validate before calling
if (preservePitch !== undefined && typeof preservePitch !== 'boolean') {
throw new Error(`preservePitch must be boolean or undefined, got ${typeof preservePitch}`);
} Type guard
const isPreservePitch = (v: unknown): v is boolean | undefined => v === undefined || typeof v === 'boolean';
Prevention
- Type the prop as boolean | undefined in your own wrapper component so the compiler rejects strings/numbers.
- When reading preservePitch from JSON/env, coerce with === 'true' rather than passing the raw string.
- Never spread untyped API responses directly onto <Video>/<Audio>; map fields explicitly.
When it happens
Trigger: Passing preservePitch as a string ("true", "false", "yes"), a number (0/1), or any object to <Audio>/<Video>/<Html5Video>/<Html5Audio>. Common when the prop is read from JSON/config files, URL query params, or API responses where booleans get stringified.
Common situations: Reading playback settings from a JSON config or environment variable that returns "true" as a string; spreading untyped props fetched from an API into a <Video> component; migrating from a custom player that used 1/0 for pitch flags.
Related errors
- You have passed a volume of type ${typeof props.volume} to y
- You have passed a volume below 0 to your <${component} /> co
- You have passed a playbackRate of type ${typeof props.playba
- You have passed a playbackRate of ${props.playbackRate} to y
- No 'src' was passed to <Html5Audio>.
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/1a90cff42d9f7f08.
Report an issue: GitHub.