{"record":{"id":"269d1fb1d9742871","repo":"remotion-dev/remotion","slug":"the-video-duration-must-be-non-negative","errorCode":null,"errorMessage":"The video duration must be non-negative.","messagePattern":"The video duration must be non-negative\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/video-matting/src/video-timing.ts","lineNumber":75,"sourceCode":"};\n\nexport const getVideoProcessingProgress = ({\n\ttimestamp,\n\tduration,\n\tfirstVideoTimestamp,\n\tdurationInSeconds,\n}: {\n\ttimestamp: number;\n\tduration: number;\n\tfirstVideoTimestamp: number;\n\tdurationInSeconds: number;\n}): {processedDurationInSeconds: number; progress: number} => {\n\tif (!Number.isFinite(duration) || duration < 0) {\n\t\tthrow new TypeError('Video frame durations must be non-negative.');\n\t}\n\n\tif (!Number.isFinite(durationInSeconds) || durationInSeconds < 0) {\n\t\tthrow new TypeError('The video duration must be non-negative.');\n\t}\n\n\tconst rebasedTimestamp = rebaseVideoTimestamp({\n\t\ttimestamp,\n\t\tfirstVideoTimestamp,\n\t});\n\tconst processedDurationInSeconds = Math.min(\n\t\tdurationInSeconds,\n\t\tMath.max(0, rebasedTimestamp + duration),\n\t);\n\n\treturn {\n\t\tprocessedDurationInSeconds,\n\t\tprogress:\n\t\t\tdurationInSeconds === 0\n\t\t\t\t? 1\n\t\t\t\t: Math.min(1, processedDurationInSeconds / durationInSeconds),\n\t};","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/remotion-dev/remotion/blob/b2f4e34732f3c6c222ea029413e22dc402218cd7/packages/video-matting/src/video-timing.ts#L57-L93","documentation":"getVideoProcessingProgress() validates the total video duration (durationInSeconds) before computing rebased timestamps and progress. A non-finite value (NaN, Infinity) or a negative number makes progress calculation meaningless, so the library throws a TypeError instead of returning bogus data.","triggerScenarios":"Calling getVideoProcessingProgress() with durationInSeconds of a negative number, NaN, or Infinity — e.g. duration parsed from metadata that failed, an uninitialized variable, or a wrong unit sign flip.","commonSituations":"Metadata probing returning -1 for unknown duration; dividing/deriving durations with NaN inputs; passing a timestamp variable by mistake in place of the total duration.","solutions":["Ensure durationInSeconds is a finite, non-negative number of seconds before calling","If duration is unknown, obtain it via metadata probing first instead of passing a placeholder like -1","Check for NaN from earlier arithmetic (e.g. parsing failures) upstream of the call"],"exampleFix":"// before\nconst progress = getVideoProcessingProgress({durationInSeconds: -1, duration, timestamp});\n// after\nconst durationInSeconds = Math.max(0, metadata.duration); // must be finite and >= 0\nconst progress = getVideoProcessingProgress({durationInSeconds, duration, timestamp});","handlingStrategy":"validation","validationCode":"if (!Number.isFinite(durationInSeconds) || durationInSeconds < 0) throw new Error('durationInSeconds must be a finite, non-negative number');","typeGuard":"const isValidDuration = (d: unknown): d is number => typeof d === 'number' && Number.isFinite(d) && d >= 0;","tryCatchPattern":"try {\n  const p = getVideoProcessingProgress({durationInSeconds, duration, timestamp});\n} catch (e) {\n  if (e instanceof TypeError && e.message.includes('non-negative')) {\n    durationInSeconds = await probeDuration(source);\n  } else throw e;\n}","preventionTips":["Probe duration from metadata instead of using placeholders like -1","Check for NaN after any arithmetic that derives durations","Validate all numeric inputs once at the boundary of your app"],"tags":["validation","argument-check","video"],"backgroundTag":"argument-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"}