{"record":{"id":"62c8185cda5fd5c7","repo":"Stirling-Tools/Stirling-PDF","slug":"failed-to-get-canvas-context","errorCode":null,"errorMessage":"Failed to get canvas context","messagePattern":"Failed to get canvas context","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"frontend/editor/src/core/utils/imageToPdfUtils.ts","lineNumber":262,"sourceCode":"        }\n\n        let newWidth: number;\n        let newHeight: number;\n\n        if (width > height) {\n          newWidth = maxDimension;\n          newHeight = (height / width) * maxDimension;\n        } else {\n          newHeight = maxDimension;\n          newWidth = (width / height) * maxDimension;\n        }\n\n        const canvas = document.createElement(\"canvas\");\n        canvas.width = newWidth;\n        canvas.height = newHeight;\n\n        const ctx = canvas.getContext(\"2d\");\n        if (!ctx) throw new Error(\"Failed to get canvas context\");\n        ctx.drawImage(img, 0, 0, newWidth, newHeight);\n\n        const outputType = imageFile.type.startsWith(\"image/\")\n          ? imageFile.type\n          : \"image/jpeg\";\n\n        canvas.toBlob(\n          (blob) => {\n            if (!blob) {\n              reject(new Error(\"Failed to convert canvas to blob\"));\n              return;\n            }\n            const reducedFile = new File([blob], imageFile.name, {\n              type: outputType,\n            });\n            URL.revokeObjectURL(url);\n            resolve(reducedFile);\n          },","sourceCodeStart":244,"sourceCodeEnd":280,"githubUrl":"https://github.com/Stirling-Tools/Stirling-PDF/blob/9ef20dcab80b85041912f045e17a6aea1d08f969/frontend/editor/src/core/utils/imageToPdfUtils.ts#L244-L280","documentation":"Thrown inside resizeImageToMaxDimension after document.createElement(\"canvas\").getContext(\"2d\") returned null. A 2D context is null only when the browser cannot allocate a canvas backing store (memory exhaustion), when the page is running in a non-DOM/hostile context, or when an extension/policy blocks canvas rendering. The function then calls ctx.drawImage and canvas.toBlob, so without a context it cannot proceed.","triggerScenarios":"Uploading a very large image whose resized dimensions still exceed available canvas memory; running the app under a headless test runner or SSR render without a real 2D canvas polyfill; a browser privacy extension returning null from getContext to fingerprint-block canvas reads.","commonSituations":"Browser tab under heavy memory pressure from many large PDFs (this app targets 100GB+ workflows); automated tests (jsdom returns null for getContext unless canvas is configured); enterprise policy/extension disabling canvas image extraction.","solutions":["Verify the failure is environmental by logging navigator.webdriver and document.createElement('canvas').getContext('2d') in the same context.","Reduce the input image size before calling resize, or cap maxDimension lower to keep canvas backing-store within browser limits.","In test environments, configure jsdom with the 'canvas' package or skip this code path.","Detect a null context and surface a user-facing message instead of crashing the multi-tool workflow."],"exampleFix":"// before\nconst ctx = canvas.getContext(\"2d\");\nif (!ctx) throw new Error(\"Failed to get canvas context\");\n\n// after\nconst ctx = canvas.getContext(\"2d\");\nif (!ctx) {\n  throw new Error(\n    \"Failed to get canvas context: the browser blocked or cannot allocate a 2D canvas. Try a smaller image or disable privacy extensions that block canvas reads.\",\n  );\n}","handlingStrategy":"type-guard","validationCode":"function canGet2dContext(): boolean {\n  try {\n    return document.createElement(\"canvas\").getContext(\"2d\") !== null;\n  } catch {\n    return false;\n  }\n}\n\nif (!canGet2dContext()) {\n  throw new Error(\"Canvas 2D context unavailable in this environment.\");\n}","typeGuard":"const isCanvasContext = (ctx: CanvasRenderingContext2D | null): ctx is CanvasRenderingContext2D =>\n  ctx !== null;","tryCatchPattern":"try {\n  const ctx = canvas.getContext(\"2d\");\n  if (!ctx) throw new Error(\"Failed to get canvas context\");\n  // ... draw\n} catch (error) {\n  URL.revokeObjectURL(url);\n  // surface a user-facing message; do not crash the tool workflow\n  throw error;\n}","preventionTips":["Cap the input image dimensions before resizing so canvas backing-store stays within browser limits.","Feature-detect a 2D context at module init and disable image tools if unavailable.","Run image-processing tests in a real browser, not jsdom, to exercise getContext."],"tags":["canvas","browser-env","memory","image-processing"],"backgroundTag":null,"analyzedSha":"9ef20dcab80b85041912f045e17a6aea1d08f969","analyzedAt":"2026-08-13T22:11:39.827Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}