remotion-dev/remotion · error · TypeError
"${name}" must be an integer, but got ${JSON.stringify(value
Error message
"${name}" must be an integer, but got ${JSON.stringify(value)} What it means
pattern() rejects non-integer values for props that are semantically whole-pixel counters (the row/column offset 'every' divisors and similar integer-step fields). assertOptionalInteger throws when such a prop is defined but not an integer, so fractional values cannot silently corrupt the tiling math.
Source
Thrown at packages/effects/src/pattern.ts:241
return;
}
if (
!Array.isArray(value) ||
value.length !== 2 ||
value.some((item) => typeof item !== 'number' || !Number.isFinite(item))
) {
throw new TypeError(`"${name}" must be a [number, number] tuple`);
}
};
const assertOptionalInteger = (value: unknown, name: string): void => {
if (value === undefined) {
return;
}
if (!Number.isInteger(value)) {
throw new TypeError(
`"${name}" must be an integer, but got ${JSON.stringify(value)}`,
);
}
};
const validatePositive = (value: number, name: string): void => {
if (value <= 0) {
throw new TypeError(`"${name}" must be > 0`);
}
};
const validateAtLeast = (value: number, min: number, name: string): void => {
if (value < min) {
throw new TypeError(
`"${name}" must be >= ${min}, but got ${JSON.stringify(value)}`,
);
}
};View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Round the value before passing: Math.round(x) or Math.trunc(x).
- Use the prop only where a fractional value is allowed (offsetU/offsetV accept floats); keep integer fields whole.
- Coerce untyped config inputs with Number() then validate with Number.isInteger yourself first.
Example fix
// before
pattern({ rowOffsetEvery: 2.5 })
// after
pattern({ rowOffsetEvery: Math.round(animatedEvery) }) Defensive patterns
Strategy: validation
Validate before calling
// Validate integer props before calling pattern().
function asInt(v: unknown, name: string): number | undefined {
if (v === undefined) return undefined;
const n = Number(v);
if (!Number.isInteger(n)) throw new Error(`${name} must be an integer`);
return n;
}
pattern({
rowOffsetEvery: asInt(raw.rowOffsetEvery, 'rowOffsetEvery'),
columnOffsetEvery: asInt(raw.columnOffsetEvery, 'columnOffsetEvery'),
}); Type guard
const isOptionalInteger = (v: unknown): v is number => v === undefined || (typeof v === 'number' && Number.isInteger(v));
Prevention
- Round slider/animation outputs with Math.round before passing to integer props.
- Keep a typed config schema that rejects fractional values at the boundary.
- Route string inputs through Number() and an integer check before pattern().
- Reserve float values for props that accept them (offsetU/offsetV), not the integer fields.
When it happens
Trigger: Calling pattern() with rowOffsetEvery, columnOffsetEvery, rowOffset, columnOffset, gapX, gapY, or a crop prop set to a non-integer such as 2.5, or a numeric string like '3'. Validation runs in validatePatternParams before the effect renders.
Common situations: Driving integer props from a slider/animation that produces fractional values; reading counts from computed floats without rounding; passing strings from URL/config params.
Related errors
- "${name}" must be a [number, number] tuple
- "${name}" must be > 0
- "${name}" must be >= ${min}, but got ${JSON.stringify(value)
- "${name}" must be an integer, but got ${JSON.stringify(value
- "${name}" must be an integer, but got ${JSON.stringify(value
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/de9119eac2af1693.
Report an issue: GitHub.