{"record":{"id":"84de101b9826dd6e","repo":"mozilla/pdf.js","slug":"cannot-use-the-same-canvas-during-multiple-render","errorCode":null,"errorMessage":"Cannot use the same canvas during multiple render() operations. Use different canvas or ensure previous operations were cancelled or completed.","messagePattern":"Cannot use the same canvas during multiple render\\(\\) operations\\. Use different canvas or ensure previous operations were cancelled or completed\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/display/api.js","lineNumber":3398,"sourceCode":"    this._dependencyTracker = params.dependencyTracker;\n    this._imagesTracker = params.imagesTracker;\n    this._operationsFilter = operationsFilter;\n  }\n\n  get completed() {\n    return this.capability.promise.catch(function () {\n      // Ignoring errors, since we only want to know when rendering is\n      // no longer pending.\n    });\n  }\n\n  initializeGraphics({ transparency = false, optionalContentConfig }) {\n    if (this.cancelled) {\n      return;\n    }\n    if (this._canvas) {\n      if (InternalRenderTask.#canvasInUse.has(this._canvas)) {\n        throw new Error(\n          \"Cannot use the same canvas during multiple render() operations. \" +\n            \"Use different canvas or ensure previous operations were \" +\n            \"cancelled or completed.\"\n        );\n      }\n      InternalRenderTask.#canvasInUse.add(this._canvas);\n    }\n\n    if (this._pdfBug && globalThis.StepperManager?.enabled) {\n      this.stepper = globalThis.StepperManager.create(this._pageIndex);\n      this.stepper.init(this.operatorList);\n      this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();\n    }\n    const {\n      viewport,\n      transform,\n      background,\n      dependencyTracker,","sourceCodeStart":3380,"sourceCodeEnd":3416,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/display/api.js#L3380-L3416","documentation":"Thrown by InternalRenderTask.initializeGraphics when the canvas it is about to paint to is already in the static #canvasInUse WeakSet. PDF.js tracks active canvases to prevent two render() calls from racing on the same 2D context, which would corrupt the framebuffer. The guard is released only when the previous task completes, errors, or is cancelled.","triggerScenarios":"Calling page.render({ canvasContext }) twice with the same canvas/context while the first task is still running; reusing a canvas for a second render without awaiting or cancelling the first; queueing a zoom render before the previous one settled.","commonSituations":"Re-rendering on viewport change without cancelling the prior task; React/Vue components that reuse a <canvas> ref across rapid prop updates; thumbnail and main viewer sharing a canvas pool.","solutions":["Track the in-flight renderTask and call renderTask.cancel() before starting a new render on the same canvas.","Await the previous renderTask.promise (or its .catch) before issuing the next render().","Render to distinct canvases when overlapping renders are genuinely needed."],"exampleFix":"// before\npage.render({ canvasContext, viewport });\npage.render({ canvasContext, viewport: newViewport });\n\n// after\nif (this.task) {\n  this.task.cancel();\n  await this.task.promise.catch(() => {});\n}\nthis.task = page.render({ canvasContext, viewport: newViewport });","handlingStrategy":"validation","validationCode":"let currentTask = null;\nasync function renderSafe(page, params) {\n  if (currentTask) {\n    currentTask.cancel();\n    await currentTask.promise.catch(() => {});\n  }\n  currentTask = page.render(params);\n  return currentTask.promise;\n}","typeGuard":"null","tryCatchPattern":"try {\n  await page.render(params).promise;\n} catch (e) {\n  if (e.message.startsWith('Cannot use the same canvas')) {\n    // cancel prior render and retry\n  } else throw e;\n}","preventionTips":["Always store the latest renderTask so you can cancel it before the next render.","Cancel-and-await on viewport changes is the canonical pattern.","Never share a canvas across concurrent renders; if you must, use a pool."],"tags":["rendering","canvas","concurrency"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}