naptha/tesseract.js · info · Error

Not found in cache

Error message

Not found in cache

What it means

This is an internal control-flow sentinel, not a user-facing error. loadLanguage tries adapter.readCache for the .traineddata file; on a cache miss (or when cacheMethod is 'refresh'/'none', which makes readCache a no-op returning undefined) it throws 'Not found in cache' to jump into the catch block, which then downloads the language data from langPath or the jsdelivr CDN. It is caught at src/worker-script/index.js:120 and is not meant to propagate.

Source

Thrown at src/worker-script/index.js:117

  const loadAndGunzipFile = async (_lang) => {
    const lang = typeof _lang === 'string' ? _lang : _lang.code;
    const readCache = ['refresh', 'none'].includes(cacheMethod)
      ? () => Promise.resolve()
      : adapter.readCache;
    let data = null;
    let newData = false;

    // Check for existing .traineddata file in cache
    // This automatically fails if cacheMethod is set to 'refresh' or 'none'
    try {
      const _data = await readCache(`${cachePath || '.'}/${lang}.traineddata`);
      if (typeof _data !== 'undefined') {
        log(`[${workerId}]: Load ${lang}.traineddata from cache`);
        data = _data;
        dataFromCache = true;
      } else {
        throw Error('Not found in cache');
      }
    // Attempt to fetch new .traineddata file
    } catch (e) {
      newData = true;
      log(`[${workerId}]: Load ${lang}.traineddata from ${langPath}`);
      if (typeof _lang === 'string') {
        let path = null;

        // If `langPath` if not explicitly set by the user, the jsdelivr CDN is used.
        // Data supporting the Legacy model is only included if `lstmOnly` is not true.
        // This saves a significant amount of data for the majority of users that use LSTM only.
        const langPathDownload = langPath || (lstmOnly ? `https://cdn.jsdelivr.net/npm/@tesseract.js-data/${lang}/4.0.0_best_int` : `https://cdn.jsdelivr.net/npm/@tesseract.js-data/${lang}/4.0.0`);

        // For Node.js, langPath may be a URL or local file path
        // The is-url package is used to tell the difference
        // For the browser version, langPath is assumed to be a URL
        if (env !== 'node' || isURL(langPathDownload) || langPathDownload.startsWith('moz-extension://') || langPathDownload.startsWith('chrome-extension://') || langPathDownload.startsWith('file://')) { /** When langPathDownload is an URL */
          path = langPathDownload.replace(/\/$/, '');

View on GitHub (pinned to a1ca80d9e3)

Solutions

  1. Recognize this is expected library flow — no action needed if the subsequent download succeeds.
  2. If it appears in user-facing output, verify the worker-script source is unmodified and the catch at line 120 is intact.
  3. To reduce how often the path runs, set cacheMethod to 'write' so successful downloads are cached for next time.
Defensive patterns

Strategy: validation

Validate before calling

// This sentinel is internal control flow and is caught by the library itself.
// You can pre-warm the cache so the path is skipped on subsequent runs:
const fs = require('fs');
const path = require('path');
function ensureCached(cachePath, langs) {
  return langs.every((l) =>
    fs.existsSync(path.join(cachePath, `${l}.traineddata`)));
}
if (!ensureCached(options.cachePath, ['eng'])) {
  // first run will hit the network; this is expected
}

Prevention

When it happens

Trigger: Internally thrown on every cache miss: first load of any language, any load when cacheMethod is 'refresh' or 'none', or when the cache directory is empty/unwritable.

Common situations: Seen only when stepping in a debugger, when break-on-throw is enabled, or if someone modified the worker-script source and broke the try/catch. By design it precedes a normal network fetch.

Related errors


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