{"record":{"id":"f885b32bfc68b840","repo":"remotion-dev/remotion","slug":"keyframeintervalinseconds-must-be-a-positive-finit","errorCode":null,"errorMessage":"keyframeIntervalInSeconds must be a positive finite number.","messagePattern":"keyframeIntervalInSeconds must be a positive finite number\\.","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/video-matting/src/separate-video-layers.ts","lineNumber":216,"sourceCode":"\n\tif (\n\t\toptions.audio !== undefined &&\n\t\t!AUDIO_DESTINATIONS.includes(options.audio)\n\t) {\n\t\tthrow new TypeError(\n\t\t\t'audio must be one of base, foreground, both, or none.',\n\t\t);\n\t}\n\n\tresolveVideoMattingQuality(options.videoBitrate ?? 'very-high');\n\tresolveVideoMattingQuality(options.audioBitrate ?? 'medium');\n\n\tif (\n\t\toptions.keyframeIntervalInSeconds !== undefined &&\n\t\t(!Number.isFinite(options.keyframeIntervalInSeconds) ||\n\t\t\toptions.keyframeIntervalInSeconds <= 0)\n\t) {\n\t\tthrow new TypeError(\n\t\t\t'keyframeIntervalInSeconds must be a positive finite number.',\n\t\t);\n\t}\n\n\tif (\n\t\toptions.onProgress !== undefined &&\n\t\ttypeof options.onProgress !== 'function'\n\t) {\n\t\tthrow new TypeError('onProgress must be a function.');\n\t}\n\n\tif (\n\t\toptions.onModelLoadProgress !== undefined &&\n\t\ttypeof options.onModelLoadProgress !== 'function'\n\t) {\n\t\tthrow new TypeError('onModelLoadProgress must be a function.');\n\t}\n};","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/remotion-dev/remotion/blob/b2f4e34732f3c6c222ea029413e22dc402218cd7/packages/video-matting/src/separate-video-layers.ts#L198-L234","documentation":"validateOptions for separateVideoLayers() accepts an optional keyframeIntervalInSeconds for the output container; it must be a positive finite number. Non-finite values, zero, or negatives are rejected after bitrate options (which go through resolveVideoMattingQuality) are validated.","triggerScenarios":"Passing keyframeIntervalInSeconds: 0 (thinking 0 = auto), -1, NaN from a failed parseFloat, or Infinity from a division by zero.","commonSituations":"Parsing CLI flags with Number() and not checking NaN; computing the interval from fps math that divided by zero; config defaulting to 0.","solutions":["Pass a positive finite number, e.g. keyframeIntervalInSeconds: 2","Omit the option to use the library default","Guard parsed values with Number.isFinite(v) && v > 0 before calling"],"exampleFix":"// before\nconst kf = Number(process.env.KF_SECONDS); // '' -> 0\nawait separateVideoLayers({ src, outputs, keyframeIntervalInSeconds: kf });\n// after\nconst kf = Number(process.env.KF_SECONDS);\nconst opts = { src, outputs };\nif (kf > 0 && Number.isFinite(kf)) opts.keyframeIntervalInSeconds = kf;\nawait separateVideoLayers(opts);","handlingStrategy":"validation","validationCode":"if (kf !== undefined && (!Number.isFinite(kf) || kf <= 0)) throw new TypeError('keyframeIntervalInSeconds must be a positive finite number');","typeGuard":"const isPositiveFinite = (v) => typeof v === 'number' && Number.isFinite(v) && v > 0;","tryCatchPattern":"try { await separateVideoLayers(opts); } catch (e) { if (e instanceof TypeError && e.message.includes('keyframeIntervalInSeconds')) { /* fix or drop the value */ } else throw e; }","preventionTips":["Use Number.isFinite checks after any Number()/parseFloat","Don't use 0 to mean 'auto' — omit the option instead","Avoid computing intervals with divisions that can yield 0/Infinity"],"tags":["validation","numeric-range","encoding"],"backgroundTag":"value-out-of-range","analyzedSha":"b2f4e34732f3c6c222ea029413e22dc402218cd7","analyzedAt":"2026-09-09T13:27:51.281Z","contentChangedAt":"2026-09-09T13:27:51.281Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}