{"record":{"id":"f9b4a3de335d24bb","repo":"remotion-dev/remotion","slug":"htmlincanvas-width-and-height-must-be-numbers","errorCode":null,"errorMessage":"HtmlInCanvas: `width` and `height` must be numbers. Received width=${String(width)}, height=${String(height)}.","messagePattern":"HtmlInCanvas: `width` and `height` must be numbers\\. Received width=(.+?), height=(.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/HtmlInCanvas.tsx","lineNumber":251,"sourceCode":"\n\treturn Number(match[1]);\n};\n\nexport type HtmlInCanvasOnPaint = (\n\tparams: HtmlInCanvasOnPaintParams,\n) => void | Promise<void>;\n\nexport type HtmlInCanvasOnInitCleanup = () => void;\n\nexport type HtmlInCanvasOnInit = (\n\tparams: HtmlInCanvasOnPaintParams,\n) => HtmlInCanvasOnInitCleanup | Promise<HtmlInCanvasOnInitCleanup>;\n\nexport type HtmlInCanvasPixelDensity = number;\n\nfunction assertHtmlInCanvasDimensions(width: unknown, height: unknown): void {\n\tif (typeof width !== 'number' || typeof height !== 'number') {\n\t\tthrow new Error(\n\t\t\t`HtmlInCanvas: \\`width\\` and \\`height\\` must be numbers. Received width=${String(width)}, height=${String(height)}.`,\n\t\t);\n\t}\n\n\tif (!Number.isInteger(width) || width <= 0) {\n\t\tthrow new Error(\n\t\t\t`HtmlInCanvas: \\`width\\` must be a positive integer. Received: ${String(width)}.`,\n\t\t);\n\t}\n\n\tif (!Number.isInteger(height) || height <= 0) {\n\t\tthrow new Error(\n\t\t\t`HtmlInCanvas: \\`height\\` must be a positive integer. Received: ${String(height)}.`,\n\t\t);\n\t}\n}\n\nfunction resolveHtmlInCanvasPixelDensity(","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/HtmlInCanvas.tsx#L233-L269","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Pass explicit numeric width/height props, e.g. `width={1920} height={1080}`.","If pulling dimensions from a ref/getComputedStyle, parse with `Number(el.clientWidth)` or `parseInt(value, 10)`.","Avoid template literals or percentage strings for width/height on <HtmlInCanvas>; reserve CSS sizing for `style`.","Type the props as `number` in your wrapper component so TypeScript catches this at compile time."],"exampleFix":"// before\n<HtmlInCanvas width=\"100%\" height=\"auto\">...</HtmlInCanvas>\n// after\n<HtmlInCanvas width={1920} height={1080}>...</HtmlInCanvas>","handlingStrategy":"type-guard","validationCode":"if (typeof width !== 'number' || typeof height !== 'number') {\n  throw new TypeError(`width/height must be numbers; got ${typeof width}, ${typeof height}`);\n}\nreturn <HtmlInCanvas width={width} height={height}>...</HtmlInCanvas>;","typeGuard":"const isNumberPair = (w: unknown, h: unknown): w is number, h is number =>\n  typeof w === 'number' && typeof h === 'number';\n// (use a single boolean guard in real code)","tryCatchPattern":null,"preventionTips":["Type wrapper props so width/height are `number` (not string | number).","Avoid passing getComputedStyle or CSS values directly to <HtmlInCanvas>.","Use `parseInt(value, 10)` when bridging CSS strings to canvas dimensions.","Write a small unit test asserting <HtmlInCanvas> only accepts numeric dims."],"tags":["html-in-canvas","props","validation","types"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}