remotion-dev/remotion · error · Error
"fps" must be a number, but you passed a value of type ${typ
Error message
"fps" must be a number, but you passed a value of type ${typeof fps} ${location} What it means
Remotion validates the `fps` value of a composition or video config via `validateFps()` before it is used. This specific branch fires when the value passed as `fps` is not of type `number` (e.g. a string from CLI parsing, `undefined`, or `null`). The `${location}` placeholder in the message is filled with a human-readable hint of where the bad value originated (e.g. the composition id or 'the `fps` prop').
Source
Thrown at packages/core/src/validation/validate-fps.ts:7
export function validateFps(
fps: unknown,
location: string,
isGif: boolean,
): asserts fps is number {
if (typeof fps !== 'number') {
throw new Error(
`"fps" must be a number, but you passed a value of type ${typeof fps} ${location}`,
);
}
if (!Number.isFinite(fps)) {
throw new Error(
`"fps" must be a finite, but you passed ${fps} ${location}`,
);
}
if (isNaN(fps)) {
throw new Error(`"fps" must not be NaN, but got ${fps} ${location}`);
}
if (fps <= 0) {
throw new TypeError(`"fps" must be positive, but got ${fps} ${location}`);
}
View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Ensure `fps` is a literal number, e.g. `fps={30}`.
- If loading fps from env/JSON, coerce explicitly: `fps={Number(process.env.REMOTION_FPS)}`.
- Add a runtime guard before constructing the composition: `if (typeof fps !== 'number') throw ...`.
- Check the `${location}` segment of the error to find which composition or prop is at fault.
Example fix
// before
<Composition fps="30" ... />
// after
<Composition fps={30} ... /> Defensive patterns
Strategy: validation
Validate before calling
function assertFps(fps: unknown, location: string): void {
if (typeof fps !== 'number') {
throw new Error(`Invalid fps at ${location}: expected number, got ${typeof fps}`);
}
}
assertFps(myFps, 'my-comp'); Type guard
const isNumber = (v: unknown): v is number => typeof v === 'number';
Prevention
- Type fps as `number` in all config helpers.
- Coerce env/JSON values with `Number(...)` at the boundary.
- Never accept `string | number` for fps in shared utilities.
When it happens
Trigger: Passing `fps` as a non-number to a `<Composition fps={...}>`, `useVideoConfig()`, `resolveVideoConfig()`, or any config-building call that routes through `validateFps`. Typical offenders: `fps="30"` (string), `fps={null}`, `fps={undefined}`, or a value read from a JSON/env file that was not coerced.
Common situations: Reading fps from an environment variable or JSON config file (always strings), deserializing a composition config from a server payload, or passing a CSS-unit string like `"30fps"`.
Related errors
- setImageSequence accepts a Boolean Value
- outputLocation must be a string but got ${typeof newOutputLo
- Studio server port should be a number. Got ${typeof port} ($
- Caching flag must be a boolean.
- Polling must be a number or null, got ${JSON.stringify(
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/91ce928164c338d6.
Report an issue: GitHub.