mozilla/pdf.js · error · Error
Cannot use the same canvas during multiple render() operatio
Error message
Cannot use the same canvas during multiple render() operations. Use different canvas or ensure previous operations were cancelled or completed.
What it means
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.
Source
Thrown at src/display/api.js:3398
this._dependencyTracker = params.dependencyTracker;
this._imagesTracker = params.imagesTracker;
this._operationsFilter = operationsFilter;
}
get completed() {
return this.capability.promise.catch(function () {
// Ignoring errors, since we only want to know when rendering is
// no longer pending.
});
}
initializeGraphics({ transparency = false, optionalContentConfig }) {
if (this.cancelled) {
return;
}
if (this._canvas) {
if (InternalRenderTask.#canvasInUse.has(this._canvas)) {
throw new Error(
"Cannot use the same canvas during multiple render() operations. " +
"Use different canvas or ensure previous operations were " +
"cancelled or completed."
);
}
InternalRenderTask.#canvasInUse.add(this._canvas);
}
if (this._pdfBug && globalThis.StepperManager?.enabled) {
this.stepper = globalThis.StepperManager.create(this._pageIndex);
this.stepper.init(this.operatorList);
this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
}
const {
viewport,
transform,
background,
dependencyTracker,View on GitHub (pinned to 5903d58d58)
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.
Example fix
// before
page.render({ canvasContext, viewport });
page.render({ canvasContext, viewport: newViewport });
// after
if (this.task) {
this.task.cancel();
await this.task.promise.catch(() => {});
}
this.task = page.render({ canvasContext, viewport: newViewport }); Defensive patterns
Strategy: validation
Validate before calling
let currentTask = null;
async function renderSafe(page, params) {
if (currentTask) {
currentTask.cancel();
await currentTask.promise.catch(() => {});
}
currentTask = page.render(params);
return currentTask.promise;
} Type guard
null
Try / catch
try {
await page.render(params).promise;
} catch (e) {
if (e.message.startsWith('Cannot use the same canvas')) {
// cancel prior render and retry
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Invalid canvas size
- Image exceeded maximum allowed size and was removed.
- Unable to decode inline image: "${reason}".
- Type3 font load error: ${reason}
- Unknown PatternType: ${typeNum}
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/84de101b9826dd6e.
Report an issue: GitHub.