{"record":{"id":"655ddf64f25d04ba","repo":"remotion-dev/remotion","slug":"frame-frame-is-not-finite","errorCode":null,"errorMessage":"Frame ${frame} is not finite","messagePattern":"Frame (.+?) is not finite","errorType":"exception","errorClass":"RangeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/validate-frame.ts","lineNumber":21,"sourceCode":"\tdurationInFrames,\n\tframe,\n}: {\n\tframe: number;\n\tdurationInFrames: number;\n\tallowFloats: boolean;\n}) => {\n\tif (typeof frame === 'undefined') {\n\t\tthrow new TypeError(`Argument missing for parameter \"frame\"`);\n\t}\n\n\tif (typeof frame !== 'number') {\n\t\tthrow new TypeError(\n\t\t\t`Argument passed for \"frame\" is not a number: ${frame}`,\n\t\t);\n\t}\n\n\tif (!Number.isFinite(frame)) {\n\t\tthrow new RangeError(`Frame ${frame} is not finite`);\n\t}\n\n\tif (frame % 1 !== 0 && !allowFloats) {\n\t\tthrow new RangeError(\n\t\t\t`Argument for frame must be an integer, but got ${frame}`,\n\t\t);\n\t}\n\n\tif (frame < 0 && frame < -durationInFrames) {\n\t\tthrow new RangeError(\n\t\t\t`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the lowest frame that can be rendered is ${-durationInFrames}`,\n\t\t);\n\t}\n\n\tif (frame > durationInFrames - 1) {\n\t\tthrow new RangeError(\n\t\t\t`Cannot use frame ${frame}: Duration of composition is ${durationInFrames}, therefore the highest frame that can be rendered is ${\n\t\t\t\tdurationInFrames - 1","sourceCodeStart":3,"sourceCodeEnd":39,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/validate-frame.ts#L3-L39","documentation":"validateFrame throws a RangeError when frame is a number but not finite — specifically NaN, Infinity, or -Infinity (Number.isFinite is false). These usually arrive from arithmetic gone wrong (division by zero, parse failures, unbounded math).","triggerScenarios":"Dividing by zero or by a duration of zero; parseFloat on a non-numeric string yields NaN; multiplication producing Infinity; chained math where an intermediate step overflowed.","commonSituations":"Computing frame = currentTime * fps where currentTime is NaN; parseFloat('') -> NaN; dividing by fps that defaulted to 0; math on optional fields that resolved to undefined then to NaN.","solutions":["Guard the arithmetic: `const frame = Number.isFinite(raw) ? raw : 0;`.","Check inputs upstream (fps, duration) for zero/NaN before computing frame.","Use `typeof x === 'number' && !Number.isNaN(x)` validation on parsed values.","Log the intermediate values at the call site to find where NaN/Infinity originates."],"exampleFix":"// before\nconst frame = position / fps; // fps is 0 -> Infinity\n\n// after\nconst frame = fps > 0 ? position / fps : 0;","handlingStrategy":"type-guard","validationCode":"if (!Number.isFinite(frame)) {\n  frame = 0; // or handle the error case\n}\nvalidateFrame({ frame, durationInFrames, allowFloats });","typeGuard":"const isFiniteFrame = (f: unknown): f is number => typeof f === 'number' && Number.isFinite(f);","tryCatchPattern":null,"preventionTips":["Guard divisions: check divisor > 0 before dividing.","Validate parseFloat results with Number.isFinite before use.","Log intermediate computation steps when debugging NaN origins."],"tags":["remotion","frame","validation","rangeerror","nan","infinity"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}