mozilla/pdf.js · error · Error

Canvas is not specified

Error message

Canvas is not specified

What it means

Thrown by BaseCanvasFactory.reset({ canvas }, width, height) when the canvas property of the first argument is falsy. reset() reuses an existing canvas/context pair to avoid allocations, so a null canvas is a programming error — the caller lost the reference, typically by destroying it earlier.

Source

Thrown at src/display/canvas_factory.js:46

    this.#enableHWA = enableHWA;
  }

  create(width, height) {
    if (width <= 0 || height <= 0) {
      throw new Error("Invalid canvas size");
    }
    const canvas = this._createCanvas(width, height);
    return {
      canvas,
      context: canvas.getContext("2d", {
        willReadFrequently: !this.#enableHWA,
      }),
    };
  }

  reset({ canvas }, width, height) {
    if (!canvas) {
      throw new Error("Canvas is not specified");
    }
    if (width <= 0 || height <= 0) {
      throw new Error("Invalid canvas size");
    }
    canvas.width = width;
    canvas.height = height;
  }

  destroy(canvasAndContext) {
    const { canvas } = canvasAndContext;
    if (!canvas) {
      throw new Error("Canvas is not specified");
    }
    // Zeroing the width and height cause Firefox to release graphics
    // resources immediately, which can greatly reduce memory consumption.
    canvas.width = canvas.height = 0;
    canvasAndContext.canvas = null;
    canvasAndContext.context = null;

View on GitHub (pinned to 5903d58d58)

Solutions

  1. Do not call reset() after destroy(); allocate a new canvas with create() instead.
  2. Track lifecycle so reset() is only called on live canvasAndContext objects.
  3. Add a null-check before reset() and recreate if needed.

Example fix

// before
canvasFactory.destroy(c);
canvasFactory.reset(c, w, h);

// after
canvasFactory.destroy(c);
c = canvasFactory.create(w, h);
Defensive patterns

Strategy: type-guard

Validate before calling

if (canvasAndContext?.canvas) {
  canvasFactory.reset(canvasAndContext, w, h);
} else {
  canvasAndContext = canvasFactory.create(w, h);
}

Type guard

const isLiveCanvasPair = (v): v is { canvas: HTMLCanvasElement; context: CanvasRenderingContext2D } =>
  !!v && !!v.canvas && !!v.context;

Try / catch

null

Prevention

When it happens

Trigger: Calling reset({ canvas: null }, ...) after destroy() nulled canvasAndContext.canvas; passing a fresh empty object; destructuring mismatch where the canvas field name is wrong.

Common situations: Reusing a canvasAndContext across render cycles after destroy() zeroed its fields; pooling logic that hands out the same slot twice; refactoring that renamed canvas to ctx.

Related errors


AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13). Data as JSON: /api/errors/5ea98dca69298944. Report an issue: GitHub.