{"record":{"id":"65771ba888e00406","repo":"remotion-dev/remotion","slug":"canvas-capture-scale-must-be-greater-than-0","errorCode":null,"errorMessage":"Canvas capture scale must be greater than 0.","messagePattern":"Canvas capture scale must be greater than 0\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/canvas-capture-extension/src/recorder.ts","lineNumber":416,"sourceCode":"\t\twindow.addEventListener('dragover', this.#onCursorMove, true);\n\t\twindow.addEventListener('pointerdown', this.#onPointerDown, true);\n\t\twindow.addEventListener('pointerup', this.#onPointerUp, true);\n\t}\n\n\tisRecording = () => this.#recording !== null;\n\n\tstartRecording = async () => {\n\t\tif (this.#disposed) {\n\t\t\tthrow new Error('This canvas recorder has already been disposed.');\n\t\t}\n\n\t\tif (this.#recording) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst density = this.#options.getDensity();\n\t\tif (!Number.isFinite(density) || density <= 0) {\n\t\t\tthrow new Error('Canvas capture scale must be greater than 0.');\n\t\t}\n\n\t\tconst {\n\t\t\tBufferTarget,\n\t\t\tMp4OutputFormat,\n\t\t\tOutput,\n\t\t\tQUALITY_HIGH,\n\t\t\tVideoSample,\n\t\t\tVideoSampleSource,\n\t\t\tWebMOutputFormat,\n\t\t} = await import('mediabunny');\n\t\tconst target = new BufferTarget();\n\t\tconst output = new Output({\n\t\t\tformat:\n\t\t\t\tthis.#options.format === 'mp4'\n\t\t\t\t\t? new Mp4OutputFormat()\n\t\t\t\t\t: new WebMOutputFormat(),\n\t\t\ttarget,","sourceCodeStart":398,"sourceCodeEnd":434,"githubUrl":"https://github.com/remotion-dev/remotion/blob/78fe4bb3fdb5a2cd68724393d63cb223db333fa7/packages/canvas-capture-extension/src/recorder.ts#L398-L434","documentation":"At `startRecording`, after disposal/recording guards, the recorder reads `this.#options.getDensity()` and requires it to be a finite positive number. Non-finite values (NaN/Infinity) and values <= 0 are rejected before importing Mediabunny and creating the BufferTarget. The density drives the capture scale, so zero/negative scale is meaningless.","triggerScenarios":"Passing a scale/density option of 0, a negative number, NaN, or Infinity to the recorder; a UI control defaulting to 0; parsing a user-entered scale that fails `Number.isFinite`.","commonSituations":"A scale slider initialized to 0; empty/invalid input parsed to NaN; copied config with a missing density field defaulting improperly; Infinity from a divide-by-zero in density computation.","solutions":["Provide a density/scale > 0 (typically 1 for 1x, 2 for retina).","Validate the density with `Number.isFinite(d) && d > 0` before starting.","Clamp user input to a positive minimum (e.g., 0.1).","Check the option provider (`getDensity`) returns a sane default."],"exampleFix":"// before\nconst recorder = new CanvasCaptureRecorder({getDensity: () => 0});\nawait recorder.startRecording();\n\n// after\nconst recorder = new CanvasCaptureRecorder({getDensity: () => 1});\nawait recorder.startRecording();","handlingStrategy":"validation","validationCode":"function validDensity(d: unknown): d is number {\n  return typeof d === 'number' && Number.isFinite(d) && d > 0;\n}\n// before startRecording:\nconst d = options.getDensity();\nif (!validDensity(d)) throw new Error('Density must be a positive finite number.');","typeGuard":"const isValidDensity = (d: unknown): d is number =>\n  typeof d === 'number' && Number.isFinite(d) && d > 0;","tryCatchPattern":"try {\n  await recorder.startRecording();\n} catch (e) {\n  if (e instanceof Error && /scale must be greater than 0/.test(e.message)) {\n    options.setDensity(1);\n    await recorder.startRecording();\n  } else throw e;\n}","preventionTips":["Default the density option to 1.","Clamp UI scale input to a positive minimum.","Validate density before starting capture."],"tags":["canvas-capture","recorder","validation","scale"],"backgroundTag":null,"analyzedSha":"78fe4bb3fdb5a2cd68724393d63cb223db333fa7","analyzedAt":"2026-08-12T17:18:50.444Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}