remotion-dev/remotion · error · Error

HtmlInCanvas: `width` must be a positive integer. Received:

Error message

HtmlInCanvas: `width` must be a positive integer. Received: ${String(width)}.

What it means

Thrown by assertHtmlInCanvasDimensions after the type check passes, when `width` is a number but not a positive integer (zero, negative, fractional, NaN). The canvas allocation is `Math.ceil(width * pixelDensity)`, but fractional or non-positive widths produce degenerate or zero-area paint targets, so Remotion rejects them up front.

Source

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

) => 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(
	pixelDensity: HtmlInCanvasPixelDensity | undefined,
): number {
	if (pixelDensity === undefined) {
		return 1;
	}

View on GitHub (pinned to 78fe4bb3fd)

Solutions

  1. Use `Math.max(1, Math.round(value))` when computing width from dynamic data.
  2. Guard mounting <HtmlInCanvas> until dimensions are known: `{w > 0 && <HtmlInCanvas width={w} ... />}`.
  3. Avoid animating width to/from zero; instead conditionally mount/unmount the component.
  4. Confirm constants and literals are positive integers, not expressions that evaluate to fractions.

Example fix

// before
<HtmlInCanvas width={props.scale * 1.5} height={1080}>...</HtmlInCanvas>
// after
<HtmlInCanvas width={Math.max(1, Math.round(props.scale * 1.5))} height={1080}>...</HtmlInCanvas>
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isInteger(width) || width <= 0) {
  throw new RangeError(`width must be a positive integer; got ${width}`);
}

Type guard

const isPositiveInt = (n: unknown): n is number =>
  typeof n === 'number' && Number.isInteger(n) && n > 0;

Prevention

When it happens

Trigger: Passing `width={0}`, `width={-10}`, `width={1920.5}`, or `width={NaN}` to <HtmlInCanvas>; computing width from a division that yields a fraction.

Common situations: Animating dimensions and letting them cross zero; using floats from layout calculations without rounding; defaulting width to 0 before a measurement arrives.

Related errors


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