{"record":{"id":"9d3c8de9dc4c1d2f","repo":"PaddlePaddle/PaddleOCR","slug":"failed-to-create-a-2d-canvas-context","errorCode":null,"errorMessage":"Failed to create a 2D canvas context.","messagePattern":"Failed to create a 2D canvas context\\.","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"paddleocr-js/packages/core/src/platform/browser.ts","lineNumber":48,"sourceCode":"  }\n}\n\nfunction hasDomConstructor(name: string): boolean {\n  return typeof (globalThis as Record<string, unknown>)[name] !== \"undefined\";\n}\n\nexport async function sourceToImageBitmap(source: ImageSource): Promise<ImageBitmap> {\n  if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) return source;\n  if (source instanceof Blob) return createImageBitmap(source);\n  if (hasDomConstructor(\"HTMLCanvasElement\") && source instanceof HTMLCanvasElement) {\n    return createImageBitmap(source);\n  }\n  if (source instanceof ImageData) {\n    const canvas = document.createElement(\"canvas\");\n    canvas.width = source.width;\n    canvas.height = source.height;\n    const ctx = canvas.getContext(\"2d\");\n    if (!ctx) throw new Error(\"Failed to create a 2D canvas context.\");\n    ctx.putImageData(source, 0, 0);\n    return createImageBitmap(canvas);\n  }\n  if (hasDomConstructor(\"HTMLImageElement\") && source instanceof HTMLImageElement) {\n    return createImageBitmap(source);\n  }\n  throw new Error(\"Unsupported image source. Use a Blob, ImageBitmap, ImageData, canvas, or img.\");\n}\n\nasync function sourceToClonedImageBitmap(source: ImageSource): Promise<ImageBitmap> {\n  if (typeof ImageBitmap !== \"undefined\" && source instanceof ImageBitmap) {\n    return createImageBitmap(source);\n  }\n  return sourceToImageBitmap(source);\n}\n\nexport function bitmapToSourceMat(\n  cv: OpenCv,","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr-js/packages/core/src/platform/browser.ts#L30-L66","documentation":"When converting an ImageData source to an ImageBitmap, sourceToImageBitmap() creates an offscreen canvas sized to the ImageData and requests a '2d' context. If getContext('2d') returns null — the browser refused to allocate a context (out of memory, too many contexts, canvas blocked by settings/extensions) — it throws this explicit error.","triggerScenarios":"Passing ImageData to predict() in a browser where 2D canvas contexts are exhausted or blocked: heavy tab with hundreds of canvases, privacy/hardening extensions disabling canvas, headless browsers with GPU/canvas disabled, or memory pressure on the GPU process.","commonSituations":"Batch-processing many frames reusing ImageData in long-running tabs; hardened browsers (canvas blocker extensions); CI headless Chrome without proper flags.","solutions":["Convert to a Blob or ImageBitmap yourself before passing (createImageBlob accepts Blob/ImageBitmap without a canvas).","Reuse/close canvases and free bitmaps (bitmap.close()) to avoid context exhaustion.","In headless/CI Chrome, enable GPU/canvas (e.g. --enable-gpu, --disable-features that block canvas) or use a different source type."],"exampleFix":"// before\nconst result = await ocr.predict(imageData); // ImageData path needs canvas\n\n// after\nconst blob = new Blob([imageData.data.buffer], { type: 'image/png' });\n// or render once and reuse an ImageBitmap:\nconst bmp = await createImageBitmap(imageData as unknown as ImageBitmapSource);\nconst result = await ocr.predict(bmp);","handlingStrategy":"fallback","validationCode":"// Pre-convert ImageData once; avoid the per-call canvas path entirely\nfunction canCreateCanvas2d(): boolean {\n  try { return document.createElement('canvas').getContext('2d') !== null; } catch { return false; }\n}","typeGuard":null,"tryCatchPattern":"try {\n  await ocr.predict(imageData);\n} catch (e) {\n  if (e instanceof Error && e.message === 'Failed to create a 2D canvas context.') {\n    // fall back: encode once via an existing canvas/Blob, or re-run in a fresh tab/context\n    const blob = await encodeImageData(imageData);\n    return ocr.predict(blob);\n  }\n  throw e;\n}","preventionTips":["Pass Blob or ImageBitmap sources instead of ImageData — they skip the canvas conversion path.","Close() ImageBitmaps and release canvases in long-running sessions to avoid exhausting contexts.","In headless CI browsers, verify canvas 2d works before running OCR tests."],"tags":["browser","canvas","image-source","environment","memory"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}