remotion-dev/remotion · error · Error
The "width" and "height" props must be numbers on <Img> when
Error message
The "width" and "height" props must be numbers on <Img> when effects are passed, because <Img> renders a <CanvasImage>. Use numeric props or CSS dimensions in "style".
What it means
Thrown by validateCanvasImageFallbackProps when `effects` are passed to <Img> and `width` or `height` is a string. With effects, <Img> renders a <CanvasImage> (a real canvas) whose backing store requires numeric pixel dimensions; string CSS values like '100%' or 'auto' cannot be allocated. The message directs you to use the numeric props for canvas sizing or move CSS sizing into `style`.
Source
Thrown at packages/core/src/Img.tsx:496
);
const formatPropList = (props: string[]) => {
return props.map((prop) => `"${prop}"`).join(', ');
};
const validateCanvasImageFallbackProps = ({
props,
ref,
width,
height,
}: {
readonly props: Record<string, unknown>;
readonly ref: React.Ref<HTMLImageElement> | undefined;
readonly width: ImgProps['width'];
readonly height: ImgProps['height'];
}) => {
if (typeof width === 'string' || typeof height === 'string') {
throw new Error(
'The "width" and "height" props must be numbers on <Img> when effects are passed, because <Img> renders a <CanvasImage>. Use numeric props or CSS dimensions in "style".',
);
}
const conflictingProps = getIncompatiblePropNames(props);
if (ref !== null && ref !== undefined) {
conflictingProps.unshift('ref');
}
if (conflictingProps.length === 0) {
return;
}
throw new Error(
`The ${formatPropList(conflictingProps)} prop${
conflictingProps.length === 1 ? '' : 's'
} cannot be used on <Img> when effects are passed, because <Img> renders a <canvas> instead of a native <img>. Remove ${
conflictingProps.length === 1 ? 'this prop' : 'these props'View on GitHub (pinned to 78fe4bb3fd)
Solutions
- Switch to numeric props: `width={1920} height={1080}` when using effects.
- Move CSS sizing into `style={{ width: '100%', height: 'auto' }}` while keeping numeric width/height props for the canvas.
- If you need CSS-only sizing, drop the `effects` prop to fall back to a native <img>.
- Type your wrapper component so width/height are `number` when effects are present.
Example fix
// before
<Img src={url} width="100%" height="auto" effects={[blur]} />
// after
<Img src={url} width={1920} height={1080} style={{width: '100%', height: 'auto'}} effects={[blur]} /> Defensive patterns
Strategy: type-guard
Validate before calling
if (effects.length > 0 && (typeof width === 'string' || typeof height === 'string')) {
throw new TypeError('Use numeric width/height (or style) when passing effects to <Img>');
} Type guard
const isNumericDimensions = ( w: string | number | undefined, h: string | number | undefined, ): boolean => typeof w !== 'string' && typeof h !== 'string';
Prevention
- Type Img-with-effects wrappers so width/height are `number`.
- Move CSS sizing into `style` when using effects.
- Drop `effects` if you need CSS-only string sizing.
- Add a unit test asserting effects + numeric dims render successfully.
When it happens
Trigger: Passing `effects` plus `width="1920"` or `width="100%"` on <Img>; using the same props you would for a CSS-sized <img> when effects are active.
Common situations: Adding an effect to an existing <Img> that previously used string dimensions; sharing a props object between canvas and non-canvas image usages.
Related errors
- The ${formatPropList(conflictingProps)} prop${conflictingPro
- No "src" prop was passed to <Img>.
- <Solid>: `pixelDensity` must be a positive finite number. Re
- Emoji ${emoji} not found. Available emojis: ${emojis.map((e)
- No id for composition passed.
AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12).
Data as JSON: /api/errors/4cef0d592a3fee70.
Report an issue: GitHub.