{"record":{"id":"77af0da837adaf97","repo":"PaddlePaddle/PaddleOCR","slug":"worker-mode-requires-offscreencanvas-support-in-th","errorCode":null,"errorMessage":"Worker mode requires OffscreenCanvas support in this browser.","messagePattern":"Worker mode requires OffscreenCanvas support in this browser\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"paddleocr-js/packages/core/src/platform/worker.ts","lineNumber":17,"sourceCode":"/*\n * Copyright (c) 2026 PaddlePaddle Authors. All Rights Reserved.\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { OpenCv, Mat } from \"@techstark/opencv-js\";\nimport type { SourceMatResult } from \"./browser\";\nimport { ensureServedFromHttp } from \"./browser\";\n\nexport interface WorkerSourcePayload {\n  kind: \"imageBitmap\";\n  imageBitmap: ImageBitmap;\n}\n\nfunction imageBitmapToImageData(imageBitmap: ImageBitmap): ImageData {\n  if (typeof OffscreenCanvas !== \"function\") {\n    throw new Error(\"Worker mode requires OffscreenCanvas support in this browser.\");\n  }\n  const canvas = new OffscreenCanvas(imageBitmap.width, imageBitmap.height);\n  const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n  if (!ctx) {\n    throw new Error(\"Failed to create a 2D canvas context in the OCR worker.\");\n  }\n  ctx.drawImage(imageBitmap, 0, 0);\n  return ctx.getImageData(0, 0, imageBitmap.width, imageBitmap.height);\n}\n\nfunction imageDataToMat(cv: OpenCv, imageData: ImageData): Mat {\n  return cv.matFromArray(imageData.height, imageData.width, cv.CV_8UC4, imageData.data);\n}\n\nfunction isWorkerSourcePayload(source: unknown): source is WorkerSourcePayload {\n  if (typeof source !== \"object\" || source === null) return false;\n  const candidate = source as Record<string, unknown>;\n  return (","sourceCodeStart":1,"sourceCodeEnd":35,"githubUrl":"https://github.com/PaddlePaddle/PaddleOCR/blob/2661c7c0ef5c613e8f93c6e93b2e052399f0f854/paddleocr-js/packages/core/src/platform/worker.ts#L1-L35","documentation":"Thrown inside the OCR worker (worker.ts imageBitmapToImageData) when OffscreenCanvas is not a constructor. The worker converts the transferred ImageBitmap into ImageData for OpenCV.js using an OffscreenCanvas, since DOM canvas is unavailable in worker scope. This gate fires when the browser supports ImageBitmap but not OffscreenCanvas (or when OffscreenCanvas is disabled by flag/policy).","triggerScenarios":"Worker mode enabled on browsers lacking OffscreenCanvas: Safari < 16.4, older Firefox versions; headless/automation environments where the feature is disabled; some locked-down enterprise browser policies.","commonSituations":"Safari 15/16.0-16.3 users (ImageBitmap yes, OffscreenCanvas no); older Android WebViews; CI browser matrices that include older versions.","solutions":["Feature-detect OffscreenCanvas (in a worker scope) before enabling worker mode and fall back to main-thread OCR","Serve the main bundle that detects support and disables the worker path for those browsers","Update Safari to >= 16.4 or use a Chromium/Firefox >= 105 browser"],"exampleFix":"// before\nconst ocr = await PaddleOCR.create({ worker: true }); // throws in Safari 16.0 worker\n\n// after\nconst offscreenOK = (() => {\n  try { return typeof OffscreenCanvas === \"function\"; } catch { return false; }\n})();\nconst ocr = await PaddleOCR.create({ worker: offscreenOK });","handlingStrategy":"validation","validationCode":"function offscreenCanvasSupportedInWorker(): Promise<boolean> {\n  return new Promise(resolve => {\n    try {\n      const w = new Worker(URL.createObjectURL(new Blob([\n        \"self.postMessage(typeof OffscreenCanvas === 'function')\"\n      ], { type: 'text/javascript' })));\n      w.onmessage = e => { resolve(Boolean(e.data)); w.terminate(); };\n      w.onerror = () => resolve(false);\n    } catch { resolve(false); }\n  });\n}","typeGuard":"const hasOffscreenCanvas = typeof OffscreenCanvas === \"function\";","tryCatchPattern":null,"preventionTips":["Detect OffscreenCanvas in the actual worker scope, not only the main thread","Gate worker mode on both ImageBitmap and OffscreenCanvas checks","Maintain a fallback to main-thread OCR for Safari < 16.4"],"tags":["worker","offscreencanvas","browser-support","feature-detection"],"backgroundTag":null,"analyzedSha":"2661c7c0ef5c613e8f93c6e93b2e052399f0f854","analyzedAt":"2026-08-14T20:17:30.180Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}