{"record":{"id":"677c0c41fa58c705","repo":"remotion-dev/remotion","slug":"the-times-prop-of-a-loop-must-be-at-least-0-but","errorCode":null,"errorMessage":"The \"times\" prop of a loop must be at least 0, but got ${times}","messagePattern":"The \"times\" prop of a loop must be at least 0, but got (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/loop/index.tsx","lineNumber":65,"sourceCode":"\tvalidateDurationInFrames(durationInFrames, {\n\t\tcomponent: 'of the <Loop /> component',\n\t\tallowFloats: true,\n\t});\n\n\tif (typeof times !== 'number') {\n\t\tthrow new TypeError(\n\t\t\t`You passed to \"times\" an argument of type ${typeof times}, but it must be a number.`,\n\t\t);\n\t}\n\n\tif (times !== Infinity && times % 1 !== 0) {\n\t\tthrow new TypeError(\n\t\t\t`The \"times\" prop of a loop must be an integer, but got ${times}.`,\n\t\t);\n\t}\n\n\tif (times < 0) {\n\t\tthrow new TypeError(\n\t\t\t`The \"times\" prop of a loop must be at least 0, but got ${times}`,\n\t\t);\n\t}\n\n\tconst maxTimes = Math.ceil(compDuration / durationInFrames);\n\tconst actualTimes = Math.min(maxTimes, times);\n\tconst style = props.layout === 'none' ? undefined : props.style;\n\tconst maxFrame = durationInFrames * (actualTimes - 1);\n\tconst iteration = Math.floor(currentFrame / durationInFrames);\n\tconst start = iteration * durationInFrames;\n\tconst from = Math.min(start, maxFrame);\n\n\tconst loopDisplay: LoopDisplay = useMemo(() => {\n\t\treturn {\n\t\t\tnumberOfTimes: Math.min(compDuration / durationInFrames, times),\n\t\t\tstartOffset: -from,\n\t\t\tdurationInFrames,\n\t\t};","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/loop/index.tsx#L47-L83","documentation":"Even after `times` is confirmed to be a valid integer, Remotion rejects negative values because a loop cannot repeat a negative number of times. Zero is explicitly allowed (the check is `times < 0`), so the floor is 0 and renders no iterations.","triggerScenarios":"Passing times={-1}, times={-5}, or any negative integer. Arithmetic such as `baseCount - extra` that can go negative.","commonSituations":"Subtracting an offset from a base count without clamping; user input controls that allow negative numbers; conditional logic producing a negative result.","solutions":["Clamp to the minimum: times={Math.max(0, value)}.","Validate/sanitize user input before passing it to <Loop>.","Pass 0 intentionally if rendering nothing is desired."],"exampleFix":"// before\n<Loop durationInFrames={30} times={count - extra} />\n// after\n<Loop durationInFrames={30} times={Math.max(0, count - extra)} />","handlingStrategy":"validation","validationCode":"const safeTimes = Math.max(0, Math.round(Number(times)));","typeGuard":"const isNonNegInt = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isInteger(v) && v >= 0;","tryCatchPattern":null,"preventionTips":["Clamp derived counts with Math.max(0, ...).","Reject negative values at the input/UI layer before they reach <Loop>."],"tags":["loop","validation","props","range"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}