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

  1. Switch to numeric props: `width={1920} height={1080}` when using effects.
  2. Move CSS sizing into `style={{ width: '100%', height: 'auto' }}` while keeping numeric width/height props for the canvas.
  3. If you need CSS-only sizing, drop the `effects` prop to fall back to a native <img>.
  4. 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

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


AI-assisted analysis of remotion-dev/remotion@78fe4bb3fd (2026-08-12). Data as JSON: /api/errors/4cef0d592a3fee70. Report an issue: GitHub.