naptha/tesseract.js · error · Error

File could not be read! Code=${code}

Error message

File could not be read! Code=${code}

What it means

In the browser worker's loadImage, File/Blob/Canvas inputs flow through readFromBlobOrFile, which uses FileReader.readAsArrayBuffer. If the reader's onerror fires, the promise rejects with the FileReader error code. Standard DOM error codes: 1=NOT_FOUND_ERR, 2=SECURITY_ERR, 3=ABORT_ERR, 4=NOT_READABLE_ERR, 12=SYNTAX_ERR, 13=ENCODING_ERR.

Source

Thrown at src/worker/browser/loadImage.js:17

'use strict';

/**
 * readFromBlobOrFile
 *
 * @name readFromBlobOrFile
 * @function
 * @access private
 */
const readFromBlobOrFile = (blob) => (
  new Promise((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.onload = () => {
      resolve(fileReader.result);
    };
    fileReader.onerror = ({ target: { error: { code } } }) => {
      reject(Error(`File could not be read! Code=${code}`));
    };
    fileReader.readAsArrayBuffer(blob);
  })
);

/**
 * loadImage
 *
 * @name loadImage
 * @function load image from different source
 * @access private
 */
const loadImage = async (image) => {
  let data = image;
  if (typeof image === 'undefined') {
    return 'undefined';
  }

View on GitHub (pinned to a1ca80d9e3)

Solutions

  1. Map the code: 1 -> file missing, 2 -> security/tainted, 4 -> permissions/lock; act accordingly (re-prompt, fix CORS, release lock).
  2. Do not call URL.revokeObjectURL on a blob URL before passing the blob to the worker.
  3. For cross-origin canvas sources, set img.crossOrigin = 'anonymous' and serve images with proper CORS headers.
  4. Validate the File/Blob is non-empty and still readable (size > 0, type set) before handing it to recognize/detect.

Example fix

// before
const url = URL.createObjectURL(blob);
URL.revokeObjectURL(url); // revoked too early
await worker.recognize(blob); // code 4 / security

// after
const url = URL.createObjectURL(blob);
await worker.recognize(blob);
URL.revokeObjectURL(url); // revoke only after recognize resolves
Defensive patterns

Strategy: validation

Validate before calling

// Validate File/Blob is non-empty and still readable before handing it to the worker.
function assertReadableBlob(blob) {
  if (!(blob instanceof Blob)) throw new Error('Expected Blob/File');
  if (blob.size === 0) throw new Error('Blob is empty');
  if (blob.isClosed) throw new Error('Blob is closed');
}
assertReadableBlob(file);
await worker.recognize(file);

Type guard

const isReadableFile = (f) =>
  (f instanceof File || f instanceof Blob) &&
  f.size > 0 &&
  !f.isClosed;

Try / catch

const FILE_ERROR_CODES = { 1: 'NOT_FOUND', 2: 'SECURITY', 3: 'ABORT', 4: 'NOT_READABLE' };
try {
  await worker.recognize(file);
} catch (e) {
  const m = e.message.match(/Code=(\d+)/);
  if (m && FILE_ERROR_CODES[m[1]] === 'NOT_READABLE') {
    // prompt user to re-select the file, then retry
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: Passing a File whose underlying file was moved/deleted after selection; a Blob backed by a revoked object URL; a cross-origin-tainted canvas; a file the OS refuses to read (permissions/lock); an aborted read.

Common situations: User selects a file in an <input type=file> then the file disappears; URL.createObjectURL blob revoked too early; canvas drawn with cross-origin images without crossOrigin='anonymous'; security policy in the worker context blocking file reads.

Related errors


AI-assisted analysis of naptha/tesseract.js@a1ca80d9e3 (2026-08-13). Data as JSON: /api/errors/d680091e1f7e7e95. Report an issue: GitHub.