remotion-dev/remotion · error · TypeError
'expiresIn' should not be NaN, but is NaN
Error message
'expiresIn' should not be NaN, but is NaN
What it means
Thrown by validatePresignExpiration() when expiresIn is a number but equals NaN. Presigned URLs require a real TTL in seconds; AWS rejects NaN-derived signatures. The check runs after the typeof-number guard, so only a numeric NaN reaches it.
Source
Thrown at packages/lambda-client/src/validate-presign-expiration.ts:18
const MAX_PRESIGN_EXPIRATION = 604800;
const MIN_PRESIGN_EXPIRATION = 1;
export const validatePresignExpiration = (presignExpiration: unknown) => {
if (typeof presignExpiration === 'undefined' || presignExpiration === null) {
return;
}
if (typeof presignExpiration !== 'number') {
throw new TypeError(
`'expiresIn' should be a number, but is ${JSON.stringify(
presignExpiration,
)}`,
);
}
if (Number.isNaN(presignExpiration)) {
throw new TypeError(`'expiresIn' should not be NaN, but is NaN`);
}
if (!Number.isFinite(presignExpiration)) {
throw new TypeError(
`'expiresIn' should be finite but is ${presignExpiration}`,
);
}
if (presignExpiration % 1 !== 0) {
throw new TypeError(
`'expiresIn' should be an integer but is ${JSON.stringify(
presignExpiration,
)}`,
);
}
if (presignExpiration > MAX_PRESIGN_EXPIRATION) {
throw new TypeError(View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Guard the parse with Number.isFinite() and fall back to undefined (let the library default) or a known good value.
- Validate the source string with /^\d+$/ before parseInt.
- Skip passing expiresIn when the input is missing rather than forwarding NaN.
Example fix
// before
const expiresIn = Number(process.env.EXPIRES_IN); // NaN
await renderMediaOnLambda({..., opts: {expiresIn}});
// after
const raw = Number(process.env.EXPIRES_IN);
const expiresIn = Number.isFinite(raw) ? raw : undefined;
await renderMediaOnLambda({..., opts: {expiresIn}}); Defensive patterns
Strategy: type-guard
Validate before calling
const raw = Number(process.env.EXPIRES_IN); const expiresIn = Number.isFinite(raw) ? raw : undefined;
Type guard
const isValidExpiresIn = (v: unknown): v is number => typeof v === 'number' && !Number.isNaN(v) && Number.isFinite(v);
Prevention
- Always pair Number() with Number.isFinite() when parsing external input.
- Pass undefined to opt into the default instead of forwarding NaN.
- Add a config-schema validator (e.g. zod) at app start.
When it happens
Trigger: Passing expiresIn: Number(someUnsetVar) (NaN), expiresIn: parseInt('abc', 10) (NaN), or any arithmetic that yields NaN.
Common situations: Env-var parse where the variable is empty/non-numeric; a formula like (a - b) where both are undefined producing NaN.
Related errors
- 'expiresIn' should be a number, but is ${JSON.stringify(pres
- 'expiresIn' should be finite but is ${presignExpiration}
- 'expiresIn' should be an integer but is ${JSON.stringify(pre
- maxRetries must be a number, but is ${JSON.stringify(maxRetr
- maxRetries must be finite, but is ${maxRetries}
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/f53a529ee24938a0.
Report an issue: GitHub.