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

  1. Validate the image opens in a viewer or via an image library before passing it to Tesseract.
  2. Convert to PNG or JPEG upstream (e.g. canvas.toBlob, sharp) which Leptonica reliably reads.
  3. For base64, ensure the data URL matches /data:image\/([a-zA-Z]*);base64,([^\"]*)/.
  4. 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

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.