{"record":{"id":"fa89e81e7465a744","repo":"remotion-dev/remotion","slug":"htmlincanvas-width-must-be-a-positive-integer","errorCode":null,"errorMessage":"HtmlInCanvas: `width` must be a positive integer. Received: ${String(width)}.","messagePattern":"HtmlInCanvas: `width` must be a positive integer\\. Received: (.+?)\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/core/src/HtmlInCanvas.tsx","lineNumber":257,"sourceCode":") => 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(\n\tpixelDensity: HtmlInCanvasPixelDensity | undefined,\n): number {\n\tif (pixelDensity === undefined) {\n\t\treturn 1;\n\t}\n","sourceCodeStart":239,"sourceCodeEnd":275,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/core/src/HtmlInCanvas.tsx#L239-L275","documentation":"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.","triggerScenarios":"Passing `width={0}`, `width={-10}`, `width={1920.5}`, or `width={NaN}` to <HtmlInCanvas>; computing width from a division that yields a fraction.","commonSituations":"Animating dimensions and letting them cross zero; using floats from layout calculations without rounding; defaulting width to 0 before a measurement arrives.","solutions":["Use `Math.max(1, Math.round(value))` when computing width from dynamic data.","Guard mounting <HtmlInCanvas> until dimensions are known: `{w > 0 && <HtmlInCanvas width={w} ... />}`.","Avoid animating width to/from zero; instead conditionally mount/unmount the component.","Confirm constants and literals are positive integers, not expressions that evaluate to fractions."],"exampleFix":"// before\n<HtmlInCanvas width={props.scale * 1.5} height={1080}>...</HtmlInCanvas>\n// after\n<HtmlInCanvas width={Math.max(1, Math.round(props.scale * 1.5))} height={1080}>...</HtmlInCanvas>","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(width) || width <= 0) {\n  throw new RangeError(`width must be a positive integer; got ${width}`);\n}","typeGuard":"const isPositiveInt = (n: unknown): n is number =>\n  typeof n === 'number' && Number.isInteger(n) && n > 0;","tryCatchPattern":null,"preventionTips":["Round dynamic widths with `Math.max(1, Math.round(value))`.","Defer mounting until a real measurement is available.","Avoid animating width through zero.","Add eslint no-magic-numbers or a wrapper assert in test builds."],"tags":["html-in-canvas","validation","dimensions","math"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}