siyuan-note/siyuan · error · Error

Unable to create a canvas context for the PDF rectangle anno

Error message

Unable to create a canvas context for the PDF rectangle annotation

What it means

This error is thrown in app/src/asset/anno.ts when rendering a PDF page region onto a newly created canvas for a rectangle (rect) annotation screenshot. `canvas.getContext("2d")` returned null, so there is no 2D drawing context to pass to pdf.js's `page.render({canvasContext})`. A null context means the browser refused or failed to allocate a rendering context for the canvas element.

Source

Thrown at app/src/asset/anno.ts:1114

    if (captureScale <= 0) {
        throw new Error("PDF rectangle annotation has invalid coordinates");
    }

    const viewport = pdfPage.getViewport({scale: captureScale, rotation: totalRotation});
    const captureBounds = getCaptureCanvasBounds(viewport.convertToViewportRectangle(position));
    const captureViewport = pdfPage.getViewport({
        scale: captureScale,
        rotation: totalRotation,
        offsetX: -captureBounds.left,
        offsetY: -captureBounds.top,
    });
    const captureCanvas = document.createElement("canvas");
    captureCanvas.width = captureBounds.width;
    captureCanvas.height = captureBounds.height;

    const captureCtx = captureCanvas.getContext("2d");
    if (!captureCtx) {
        throw new Error("Unable to create a canvas context for the PDF rectangle annotation");
    }
    await pdfPage.render({
        canvasContext: captureCtx,
        viewport: captureViewport,
    }).promise;

    const displayViewport = pdfPage.getViewport({scale: PDF_RECT_DISPLAY_SCALE, rotation: totalRotation});
    const displayWidth = Math.min(
        getCaptureDisplayWidth(displayViewport.convertToViewportRectangle(position)),
        captureBounds.width,
    );
    const blob = await new Promise<Blob>((resolve, reject) => {
        captureCanvas.toBlob((result) => {
            if (result) {
                resolve(result);
            } else {
                reject(new Error("Unable to encode the PDF rectangle annotation"));
            }

View on GitHub (pinned to 8641553a1f)

Solutions

  1. Reduce captureBounds.width/height (cap by device pixel ratio / zoom) before creating the canvas so it stays within browser limits
  2. Check the browser/environment: iOS Safari and WKWebView have strict canvas memory limits; retry with a smaller canvas or lower scale factor
  3. Verify the canvas is not detached/tainted and that hardware acceleration or GPU processes are not disabled in the runtime (Electron flags, --disable-gpu)
  4. Wrap the getContext call and fall back to re-creating a smaller canvas once before surfacing the error

Example fix

// before
const captureCanvas = document.createElement("canvas");
captureCanvas.width = captureBounds.width;
captureCanvas.height = captureBounds.height;
const captureCtx = captureCanvas.getContext("2d");
if (!captureCtx) {
    throw new Error("Unable to create a canvas context for the PDF rectangle annotation");
}
// after
const MAX_AREA = 16777216; // 4096x4096, safe on iOS
const scale = Math.min(1, MAX_AREA / (captureBounds.width * captureBounds.height));
const captureCanvas = document.createElement("canvas");
captureCanvas.width = Math.floor(captureBounds.width * scale);
captureCanvas.height = Math.floor(captureBounds.height * scale);
const captureCtx = captureCanvas.getContext("2d");
if (!captureCtx) {
    throw new Error("Unable to create a canvas context for the PDF rectangle annotation");
}
Defensive patterns

Strategy: fallback

Validate before calling

const MAX_AREA = 16777216;
if (captureBounds.width * captureBounds.height > MAX_AREA) {
    // scale down bounds before creating the canvas
}

Type guard

function has2DContext(canvas: HTMLCanvasElement): canvas is HTMLCanvasElement & {getContext: (t: "2d") => CanvasRenderingContext2D} {
    return !!canvas.getContext("2d");
}

Try / catch

try {
    await renderRectAnnotationCapture(page, bounds);
} catch (e) {
    if (e.message.includes("canvas context")) {
        // retry once with a halved-scale canvas, else show a user-facing hint
    }
}

Prevention

When it happens

Trigger: Calling the rectangle-annotation screenshot/export path in app/src/asset/anno.ts:1114 when `captureCanvas.getContext("2d")` returns null right after a canvas is created with captureBounds dimensions and before `pdfPage.render(...)` is awaited.

Common situations: Very large captureBounds producing a canvas exceeding the browser's max canvas area (e.g. zoomed/high-DPI PDF pages on mobile Safari or iOS WKWebView, where total canvas memory is capped); the page running in an environment with canvas disabled or GPU process crash; memory pressure on embedded webviews preventing context allocation.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of siyuan-note/siyuan@8641553a1f (2026-09-11). Data as JSON: /api/errors/c0b01b8f1081f8b4. Report an issue: GitHub.