{"record":{"id":"0849f9cfa6da39ad","repo":"naptha/tesseract.js","slug":"error-attempting-to-read-image","errorCode":null,"errorMessage":"Error attempting to read image.","messagePattern":"Error attempting to read image\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/worker-script/utils/setImage.js","lineNumber":33,"sourceCode":"\n  const exif = parseInt(image.slice(0, 500).join(' ').match(/1 18 0 3 0 0 0 1 0 (\\d)/)?.[1], 10) || 1;\n\n  // /*\n  //  * Leptonica supports some but not all bmp files\n  //  * @see https://github.com/DanBloomberg/leptonica/issues/607#issuecomment-1068802516\n  //  * We therefore use bmp-js to convert all bmp files into a format Leptonica is known to support\n  //  */\n  if (isBmp) {\n    // Not sure what this line actually does, but removing breaks the function\n    const buf = Buffer.from(Array.from({ ...image, length: Object.keys(image).length }));\n    const bmpBuf = bmp.decode(buf);\n    TessModule.FS.writeFile('/input', bmp.encode(bmpBuf).data);\n  } else {\n    TessModule.FS.writeFile('/input', image);\n  }\n\n  const res = api.SetImageFile(exif, angle);\n  if (res === 1) throw Error('Error attempting to read image.');\n};\n","sourceCodeStart":15,"sourceCodeEnd":35,"githubUrl":"https://github.com/naptha/tesseract.js/blob/a1ca80d9e31c34512d0ded75ff8821ddcf3f2f91/src/worker-script/utils/setImage.js#L15-L35","documentation":"setImage writes the image bytes to the worker's virtual filesystem at /input (decoding BMP via bmp-js first) and then calls api.SetImageFile(exif, angle). A return value of 1 means Leptonica could not read or decode the file. The throw originates inside recognize/detect handlers and is forwarded to the caller as a job rejection.","triggerScenarios":"Unsupported image format (e.g. HEIC, WebP in older Leptonica, proprietary RAW); corrupt or truncated bytes; empty Uint8Array; raw pixel buffer misinterpreted as an encoded image; an HTML error page returned in place of image bytes from a fetch; malformed BMP that bmp-js cannot decode.","commonSituations":"Passing a Uint8Array of pixel data instead of an encoded file; broken base64 data URL; fetch() resolving with a non-image response; image produced by a pipeline that strips headers; very large images hitting memory limits during decode.","solutions":["Validate the image opens in a viewer or via an image library before passing it to Tesseract.","Convert to PNG or JPEG upstream (e.g. canvas.toBlob, sharp) which Leptonica reliably reads.","For base64, ensure the data URL matches /data:image\\/([a-zA-Z]*);base64,([^\\\"]*)/.","Confirm a fetched URL actually returns image bytes (check Content-Type) rather than an error page."],"exampleFix":"// before\nconst resp = await fetch(url);\nconst data = await resp.arrayBuffer(); // may be HTML error page\nawait worker.recognize(new Uint8Array(data)); // SetImageFile returns 1\n\n// after\nconst resp = await fetch(url);\nif (!resp.ok || !resp.headers.get('content-type')?.startsWith('image/')) {\n  throw new Error('not an image');\n}\nconst data = await resp.arrayBuffer();\nawait worker.recognize(new Uint8Array(data));","handlingStrategy":"validation","validationCode":"// Validate bytes are a decodable image before sending to the worker.\nconst IMAGE_SIGS = {\n  png: [0x89, 0x50, 0x4E, 0x47],\n  jpg: [0xFF, 0xD8, 0xFF],\n  gif: [0x47, 0x49, 0x46],\n  bmp: [0x42, 0x4D],\n};\nfunction looksLikeImage(bytes) {\n  const u = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);\n  return Object.values(IMAGE_SIGS).some((sig) => sig.every((b, i) => u[i] === b));\n}\nif (!looksLikeImage(imageBytes) || imageBytes.length === 0) {\n  throw new Error('Input is not a recognized encoded image');\n}\nawait worker.recognize(imageBytes);","typeGuard":"const isEncodedImageBytes = (b) =>\n  (b instanceof Uint8Array || ArrayBuffer.isView(b)) &&\n  b.length >= 4 &&\n  [[0x89,0x50,0x4E,0x47],[0xFF,0xD8,0xFF],[0x47,0x49,0x46],[0x42,0x4D]]\n    .some((sig) => sig.every((v, i) => b[i] === v));","tryCatchPattern":"try {\n  const { data } = await worker.recognize(image);\n} catch (e) {\n  if (/Error attempting to read image/i.test(e.message)) {\n    // re-encode to PNG via a canvas/sharp and retry\n    const png = await reencodeToPng(image);\n    return worker.recognize(png);\n  }\n  throw e;\n}","preventionTips":["Re-encode inputs to PNG or JPEG upstream so Leptonica always sees a supported format.","Verify fetched URLs return image bytes (Content-Type starts with image/) before passing them on.","Never pass raw RGBA/pixel buffers — pass an encoded file or a canvas/img element.","For base64, confirm the data URL is complete and not truncated."],"tags":["image","leptonica","input-validation","decode"],"backgroundTag":null,"analyzedSha":"a1ca80d9e31c34512d0ded75ff8821ddcf3f2f91","analyzedAt":"2026-08-13T04:28:13.744Z","schemaVersion":2},"datasetVersion":"2026-08-13T09:17:06.757Z"}