naptha/tesseract.js · error · Error
Error attempting to read image.
Error message
Error attempting to read image.
What it means
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.
Source
Thrown at src/worker-script/utils/setImage.js:33
const exif = parseInt(image.slice(0, 500).join(' ').match(/1 18 0 3 0 0 0 1 0 (\d)/)?.[1], 10) || 1;
// /*
// * Leptonica supports some but not all bmp files
// * @see https://github.com/DanBloomberg/leptonica/issues/607#issuecomment-1068802516
// * We therefore use bmp-js to convert all bmp files into a format Leptonica is known to support
// */
if (isBmp) {
// Not sure what this line actually does, but removing breaks the function
const buf = Buffer.from(Array.from({ ...image, length: Object.keys(image).length }));
const bmpBuf = bmp.decode(buf);
TessModule.FS.writeFile('/input', bmp.encode(bmpBuf).data);
} else {
TessModule.FS.writeFile('/input', image);
}
const res = api.SetImageFile(exif, angle);
if (res === 1) throw Error('Error attempting to read image.');
};
View on GitHub (pinned to a1ca80d9e3)
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.
Example fix
// before
const resp = await fetch(url);
const data = await resp.arrayBuffer(); // may be HTML error page
await worker.recognize(new Uint8Array(data)); // SetImageFile returns 1
// after
const resp = await fetch(url);
if (!resp.ok || !resp.headers.get('content-type')?.startsWith('image/')) {
throw new Error('not an image');
}
const data = await resp.arrayBuffer();
await worker.recognize(new Uint8Array(data)); Defensive patterns
Strategy: validation
Validate before calling
// Validate bytes are a decodable image before sending to the worker.
const IMAGE_SIGS = {
png: [0x89, 0x50, 0x4E, 0x47],
jpg: [0xFF, 0xD8, 0xFF],
gif: [0x47, 0x49, 0x46],
bmp: [0x42, 0x4D],
};
function looksLikeImage(bytes) {
const u = bytes instanceof Uint8Array ? bytes : new Uint8Array(bytes);
return Object.values(IMAGE_SIGS).some((sig) => sig.every((b, i) => u[i] === b));
}
if (!looksLikeImage(imageBytes) || imageBytes.length === 0) {
throw new Error('Input is not a recognized encoded image');
}
await worker.recognize(imageBytes); Type guard
const isEncodedImageBytes = (b) =>
(b instanceof Uint8Array || ArrayBuffer.isView(b)) &&
b.length >= 4 &&
[[0x89,0x50,0x4E,0x47],[0xFF,0xD8,0xFF],[0x47,0x49,0x46],[0x42,0x4D]]
.some((sig) => sig.every((v, i) => b[i] === v)); Try / catch
try {
const { data } = await worker.recognize(image);
} catch (e) {
if (/Error attempting to read image/i.test(e.message)) {
// re-encode to PNG via a canvas/sharp and retry
const png = await reencodeToPng(image);
return worker.recognize(png);
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
AI-assisted analysis of naptha/tesseract.js@a1ca80d9e3 (2026-08-13).
Data as JSON: /api/errors/0849f9cfa6da39ad.
Report an issue: GitHub.