remotion-dev/remotion · error · Error

HtmlInCanvas: `width` and `height` must be numbers. Received

Error message

HtmlInCanvas: `width` and `height` must be numbers. Received width=${String(width)}, height=${String(height)}.

What it means

Thrown by assertHtmlInCanvasDimensions (a private validator inside <HtmlInCanvas>) before any render work, when `width` or `height` is not of type 'number'. <HtmlInCanvas> paints DOM into a <canvas> of exact pixel dimensions, so it cannot accept strings (like '100%') or other types the way a CSS-sized div would.

Source

Thrown at packages/core/src/HtmlInCanvas.tsx:251

	return Number(match[1]);
};

export type HtmlInCanvasOnPaint = (
	params: HtmlInCanvasOnPaintParams,
) => void | Promise<void>;

export type HtmlInCanvasOnInitCleanup = () => void;

export type HtmlInCanvasOnInit = (
	params: HtmlInCanvasOnPaintParams,
) => HtmlInCanvasOnInitCleanup | Promise<HtmlInCanvasOnInitCleanup>;

export type HtmlInCanvasPixelDensity = number;

function assertHtmlInCanvasDimensions(width: unknown, height: unknown): void {
	if (typeof width !== 'number' || typeof height !== 'number') {
		throw new Error(
			`HtmlInCanvas: \`width\` and \`height\` must be numbers. Received width=${String(width)}, height=${String(height)}.`,
		);
	}

	if (!Number.isInteger(width) || width <= 0) {
		throw new Error(
			`HtmlInCanvas: \`width\` must be a positive integer. Received: ${String(width)}.`,
		);
	}

	if (!Number.isInteger(height) || height <= 0) {
		throw new Error(
			`HtmlInCanvas: \`height\` must be a positive integer. Received: ${String(height)}.`,
		);
	}
}

function resolveHtmlInCanvasPixelDensity(

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Pass explicit numeric width/height props, e.g. `width={1920} height={1080}`.
  2. If pulling dimensions from a ref/getComputedStyle, parse with `Number(el.clientWidth)` or `parseInt(value, 10)`.
  3. Avoid template literals or percentage strings for width/height on <HtmlInCanvas>; reserve CSS sizing for `style`.
  4. Type the props as `number` in your wrapper component so TypeScript catches this at compile time.

Example fix

// before
<HtmlInCanvas width="100%" height="auto">...</HtmlInCanvas>
// after
<HtmlInCanvas width={1920} height={1080}>...</HtmlInCanvas>
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof width !== 'number' || typeof height !== 'number') {
  throw new TypeError(`width/height must be numbers; got ${typeof width}, ${typeof height}`);
}
return <HtmlInCanvas width={width} height={height}>...</HtmlInCanvas>;

Type guard

const isNumberPair = (w: unknown, h: unknown): w is number, h is number =>
  typeof w === 'number' && typeof h === 'number';
// (use a single boolean guard in real code)

Prevention

When it happens

Trigger: Passing `width="100%"`, `width="1080"` (string), `width={null}`, or omitting width/height on <HtmlInCanvas>; passing width/height derived from a ref measurement that returns a string.

Common situations: Treating <HtmlInCanvas> like a regular CSS layout component; copying responsive CSS values into canvas dimensions; reading dimensions from getComputedStyle (which returns strings) and forwarding them directly.

Related errors


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