{"record":{"id":"ace9fce5fbd87ff9","repo":"remotion-dev/remotion","slug":"the-times-prop-of-a-loop-must-be-an-integer-but","errorCode":null,"errorMessage":"The \"times\" prop of a loop must be an integer, but got ${times}.","messagePattern":"The \"times\" prop of a loop must be an integer, but got (.+?)\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/loop/index.tsx","lineNumber":59,"sourceCode":"\tshowInTimeline,\n\t...props\n}) => {\n\tconst currentFrame = useCurrentFrame();\n\tconst {durationInFrames: compDuration} = useVideoConfig();\n\n\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","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/loop/index.tsx#L41-L77","documentation":"The <Loop> component repeats its child `times` times. After confirming `times` is a number, Remotion requires it to be an integer because a fractional repeat count is undefined. `Infinity` is explicitly permitted as a sentinel for \"loop forever\" (excluded by the `times !== Infinity` guard), but any other non-integer like 1.5 throws a TypeError at loop/index.tsx:59.","triggerScenarios":"Passing times={1.5}, times={2.7}, or any float to <Loop>. Deriving times from a division (e.g. compDuration / loopDuration) that yields a non-integer without rounding.","commonSituations":"Computing loop count from composition math (compDuration / clipDuration) that does not divide evenly; binding times to a Studio slider that produces floats; copy-pasting a fractional value.","solutions":["Round the computed value: times={Math.ceil(compDuration / loopDuration)} (or Math.floor).","Pass an integer literal: times={3}.","Use Infinity to loop forever: times={Infinity}."],"exampleFix":"// before\n<Loop durationInFrames={30} times={compDuration / 30} />\n// after\n<Loop durationInFrames={30} times={Math.ceil(compDuration / 30)} />","handlingStrategy":"validation","validationCode":"const safeTimes =\n  typeof times === 'number' && (times === Infinity || Number.isInteger(times))\n    ? times\n    : Math.round(Number(times));","typeGuard":"const isLoopTimes = (v: unknown): v is number =>\n  typeof v === 'number' && (v === Infinity || Number.isInteger(v));","tryCatchPattern":null,"preventionTips":["Derive loop counts with Math.ceil/Math.floor rather than raw division.","Type the prop as `times: number` in your composition schema.","Add a Studio schema integer constraint on the times input."],"tags":["loop","validation","props","integer"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}