remotion-dev/remotion · error · TypeError
The "times" prop of a loop must be an integer, but got ${tim
Error message
The "times" prop of a loop must be an integer, but got ${times}. What it means
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.
Source
Thrown at packages/core/src/loop/index.tsx:59
showInTimeline,
...props
}) => {
const currentFrame = useCurrentFrame();
const {durationInFrames: compDuration} = useVideoConfig();
validateDurationInFrames(durationInFrames, {
component: 'of the <Loop /> component',
allowFloats: true,
});
if (typeof times !== 'number') {
throw new TypeError(
`You passed to "times" an argument of type ${typeof times}, but it must be a number.`,
);
}
if (times !== Infinity && times % 1 !== 0) {
throw new TypeError(
`The "times" prop of a loop must be an integer, but got ${times}.`,
);
}
if (times < 0) {
throw new TypeError(
`The "times" prop of a loop must be at least 0, but got ${times}`,
);
}
const maxTimes = Math.ceil(compDuration / durationInFrames);
const actualTimes = Math.min(maxTimes, times);
const style = props.layout === 'none' ? undefined : props.style;
const maxFrame = durationInFrames * (actualTimes - 1);
const iteration = Math.floor(currentFrame / durationInFrames);
const start = iteration * durationInFrames;
const from = Math.min(start, maxFrame);
View on GitHub (pinned to 78fe4bb3fd)
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}.
Example fix
// before
<Loop durationInFrames={30} times={compDuration / 30} />
// after
<Loop durationInFrames={30} times={Math.ceil(compDuration / 30)} /> Defensive patterns
Strategy: validation
Validate before calling
const safeTimes =
typeof times === 'number' && (times === Infinity || Number.isInteger(times))
? times
: Math.round(Number(times)); Type guard
const isLoopTimes = (v: unknown): v is number => typeof v === 'number' && (v === Infinity || Number.isInteger(v));
Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- The "times" prop of a loop must be at least 0, but got ${tim
- Emoji ${emoji} not found. Available emojis: ${emojis.map((e)
- No id for composition passed.
- HtmlInCanvas: `width` and `height` must be numbers. Received
- No "src" prop was passed to <Img>.
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/ace9fce5fbd87ff9.
Report an issue: GitHub.