{"record":{"id":"00eb2bce2a142687","repo":"remotion-dev/remotion","slug":"you-passed-to-times-an-argument-of-type-typeof","errorCode":null,"errorMessage":"You passed to \"times\" an argument of type ${typeof times}, but it must be a number.","messagePattern":"You passed to \"times\" an argument of type (.+?), but it must be a number\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/core/src/loop/index.tsx","lineNumber":53,"sourceCode":"\tuseLoop: typeof useLoop;\n} = ({\n\tdurationInFrames,\n\ttimes = Infinity,\n\tchildren,\n\tname,\n\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);","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/loop/index.tsx#L35-L71","documentation":"Thrown by the <Loop> component when its times prop is not a number. The prop defaults to Infinity (a number), so this only fires when an explicit non-number value — string, boolean, object, null — is passed. It is checked after validateDurationInFrames so the duration is already known valid.","triggerScenarios":"<Loop durationInFrames={30} times=\"3\">; <Loop durationInFrames={30} times={'3'}>; times sourced from JSON/props as a string and passed uncoerced; times bound to a DOM input value (string).","commonSituations":"Reading times from a config file or URL query string (always string); form inputs that yield strings; passing a React state variable typed loosely.","solutions":["Pass times as a numeric literal, e.g. <Loop durationInFrames={30} times={3}>.","Coerce the source value with Number() before passing it.","Omit times entirely to keep the default Infinity (loop for the whole composition)."],"exampleFix":"// before\n<Loop durationInFrames={30} times={\"3\"}>{children}</Loop>\n// after\n<Loop durationInFrames={30} times={Number(rawTimes)}>{children}</Loop>","handlingStrategy":"type-guard","validationCode":"if (times !== undefined && typeof times !== 'number') {\n  throw new Error('times must be a number');\n}\nreturn <Loop durationInFrames={30} times={times}>{children}</Loop>;","typeGuard":"const isLoopTimes = (v: unknown): v is number | undefined =>\n  v === undefined || typeof v === 'number';","tryCatchPattern":null,"preventionTips":["Pass times as a numeric literal, not a string.","Coerce string sources (JSON, URL params, form inputs) with Number() first.","Omit times to use the default Infinity when you want indefinite looping."],"tags":["loop","component","props","type-error"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}