{"record":{"id":"c0b01b8f1081f8b4","repo":"siyuan-note/siyuan","slug":"unable-to-create-a-canvas-context-for-the-pdf-rect","errorCode":null,"errorMessage":"Unable to create a canvas context for the PDF rectangle annotation","messagePattern":"Unable to create a canvas context for the PDF rectangle annotation","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"app/src/asset/anno.ts","lineNumber":1114,"sourceCode":"    if (captureScale <= 0) {\n        throw new Error(\"PDF rectangle annotation has invalid coordinates\");\n    }\n\n    const viewport = pdfPage.getViewport({scale: captureScale, rotation: totalRotation});\n    const captureBounds = getCaptureCanvasBounds(viewport.convertToViewportRectangle(position));\n    const captureViewport = pdfPage.getViewport({\n        scale: captureScale,\n        rotation: totalRotation,\n        offsetX: -captureBounds.left,\n        offsetY: -captureBounds.top,\n    });\n    const captureCanvas = document.createElement(\"canvas\");\n    captureCanvas.width = captureBounds.width;\n    captureCanvas.height = captureBounds.height;\n\n    const captureCtx = captureCanvas.getContext(\"2d\");\n    if (!captureCtx) {\n        throw new Error(\"Unable to create a canvas context for the PDF rectangle annotation\");\n    }\n    await pdfPage.render({\n        canvasContext: captureCtx,\n        viewport: captureViewport,\n    }).promise;\n\n    const displayViewport = pdfPage.getViewport({scale: PDF_RECT_DISPLAY_SCALE, rotation: totalRotation});\n    const displayWidth = Math.min(\n        getCaptureDisplayWidth(displayViewport.convertToViewportRectangle(position)),\n        captureBounds.width,\n    );\n    const blob = await new Promise<Blob>((resolve, reject) => {\n        captureCanvas.toBlob((result) => {\n            if (result) {\n                resolve(result);\n            } else {\n                reject(new Error(\"Unable to encode the PDF rectangle annotation\"));\n            }","sourceCodeStart":1096,"sourceCodeEnd":1132,"githubUrl":"https://github.com/siyuan-note/siyuan/blob/8641553a1f07374001902d3ce773285db1292b2d/app/src/asset/anno.ts#L1096-L1132","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Reduce captureBounds.width/height (cap by device pixel ratio / zoom) before creating the canvas so it stays within browser limits","Check the browser/environment: iOS Safari and WKWebView have strict canvas memory limits; retry with a smaller canvas or lower scale factor","Verify the canvas is not detached/tainted and that hardware acceleration or GPU processes are not disabled in the runtime (Electron flags, --disable-gpu)","Wrap the getContext call and fall back to re-creating a smaller canvas once before surfacing the error"],"exampleFix":"// before\nconst captureCanvas = document.createElement(\"canvas\");\ncaptureCanvas.width = captureBounds.width;\ncaptureCanvas.height = captureBounds.height;\nconst captureCtx = captureCanvas.getContext(\"2d\");\nif (!captureCtx) {\n    throw new Error(\"Unable to create a canvas context for the PDF rectangle annotation\");\n}\n// after\nconst MAX_AREA = 16777216; // 4096x4096, safe on iOS\nconst scale = Math.min(1, MAX_AREA / (captureBounds.width * captureBounds.height));\nconst captureCanvas = document.createElement(\"canvas\");\ncaptureCanvas.width = Math.floor(captureBounds.width * scale);\ncaptureCanvas.height = Math.floor(captureBounds.height * scale);\nconst captureCtx = captureCanvas.getContext(\"2d\");\nif (!captureCtx) {\n    throw new Error(\"Unable to create a canvas context for the PDF rectangle annotation\");\n}","handlingStrategy":"fallback","validationCode":"const MAX_AREA = 16777216;\nif (captureBounds.width * captureBounds.height > MAX_AREA) {\n    // scale down bounds before creating the canvas\n}","typeGuard":"function has2DContext(canvas: HTMLCanvasElement): canvas is HTMLCanvasElement & {getContext: (t: \"2d\") => CanvasRenderingContext2D} {\n    return !!canvas.getContext(\"2d\");\n}","tryCatchPattern":"try {\n    await renderRectAnnotationCapture(page, bounds);\n} catch (e) {\n    if (e.message.includes(\"canvas context\")) {\n        // retry once with a halved-scale canvas, else show a user-facing hint\n    }\n}","preventionTips":["Cap canvas dimensions by device pixel ratio and zoom before rendering","Test PDF annotation export on iOS/Safari where canvas memory limits are strictest","Detect getContext returning null early and degrade to a smaller-scale capture instead of throwing"],"tags":["canvas","pdf","browser-limits","frontend"],"backgroundTag":"internal-invariant-violation","analyzedSha":"8641553a1f07374001902d3ce773285db1292b2d","analyzedAt":"2026-09-11T16:08:28.414Z","contentChangedAt":"2026-09-11T16:08:28.414Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}