naptha/tesseract.js · error · Error

Legacy model requested but code missing.

Error message

Legacy model requested but code missing.

What it means

lstmOnlyCore (src/createWorker.js:36) is true when the worker was created with OEM.DEFAULT or OEM.LSTM_ONLY and the legacyCore option is not set — meaning the loaded WASM core has no legacy engine. reinitialize() throws when you then request OEM.TESSERACT_ONLY (0) or OEM.TESSERACT_LSTM_COMBINED (2), because those modes require the legacy engine that is absent from the LSTM-only core build.

Source

Thrown at src/createWorker.js:135

        cacheMethod: options.cacheMethod,
        gzip: options.gzip,
        lstmOnly: [OEM.DEFAULT, OEM.LSTM_ONLY].includes(currentOem)
          && !options.legacyLang,
      },
    },
  }));

  const initializeInternal = (_langs, _oem, _config, jobId) => (
    startJob(createJob({
      id: jobId,
      action: 'initialize',
      payload: { langs: _langs, oem: _oem, config: _config },
    }))
  );

  const reinitialize = (langs = 'eng', oem, config, jobId) => { // eslint-disable-line

    if (lstmOnlyCore && [OEM.TESSERACT_ONLY, OEM.TESSERACT_LSTM_COMBINED].includes(oem)) throw Error('Legacy model requested but code missing.');

    const _oem = oem || currentOem;
    currentOem = _oem;

    const _config = config || currentConfig;
    currentConfig = _config;

    // Only load langs that are not already loaded.
    // This logic fails if the user downloaded the LSTM-only English data for a language
    // and then uses `worker.reinitialize` to switch to the Legacy engine.
    // However, the correct data will still be downloaded after initialization fails
    // and this can be avoided entirely if the user loads the correct data ahead of time.
    const langsArr = typeof langs === 'string' ? langs.split('+') : langs;
    const _langs = langsArr.filter((x) => !currentLangs.includes(x));
    currentLangs.push(..._langs);

    if (_langs.length > 0) {
      return loadLanguageInternal(_langs, jobId)

View on GitHub (pinned to a1ca80d9e3)

Solutions

  1. Recreate the worker with legacyCore: true in options so the full core is loaded, then reinitialize to TESSERACT_ONLY/COMBINED.
  2. Create the worker directly with OEM.TESSERACT_ONLY or OEM.TESSERACT_LSTM_COMBINED instead of reinitializing.
  3. Keep reinitialize on OEM.LSTM_ONLY or OEM.DEFAULT, which the LSTM-only core supports.

Example fix

// before
const worker = await createWorker('eng'); // lstmOnlyCore = true
await worker.reinitialize('eng', OEM.TESSERACT_ONLY); // throws

// after
const worker = await createWorker('eng', OEM.TESSERACT_ONLY, { legacyCore: true, legacyLang: true });
await worker.reinitialize('eng', OEM.TESSERACT_ONLY);
Defensive patterns

Strategy: validation

Validate before calling

const OEM = require('tesseract.js').OEM;
const LEGACY_OEMS = new Set([OEM.TESSERACT_ONLY, OEM.TESSERACT_LSTM_COMBINED]);
// legacyNeeded must match the legacyCore flag passed at createWorker time
function assertLegacyAvailable(legacyCoreEnabled, requestedOem) {
  if (!legacyCoreEnabled && LEGACY_OEMS.has(requestedOem)) {
    throw new Error('Recreate the worker with legacyCore:true before requesting OEM ' + requestedOem);
  }
}
assertLegacyAvailable(options.legacyCore === true, requestedOem);
await worker.reinitialize(langs, requestedOem);

Type guard

const isLegacyOem = (oem) =>
  oem === 0 /* TESSERACT_ONLY */ || oem === 2 /* TESSERACT_LSTM_COMBINED */;

Try / catch

try {
  await worker.reinitialize(langs, requestedOem);
} catch (e) {
  if (/Legacy model requested/.test(e.message)) {
    // recreate with legacy support, then retry
    await worker.terminate();
    worker = await createWorker(langs, requestedOem, { legacyCore: true, legacyLang: true });
  } else { throw e; }
}

Prevention

When it happens

Trigger: worker.reinitialize('eng', OEM.TESSERACT_ONLY) or worker.reinitialize('eng', OEM.TESSERACT_LSTM_COMBINED) on a worker created with default options (OEM.LSTM_ONLY, no legacyCore).

Common situations: Starting with the default LSTM-only setup and later wanting legacy accuracy; following a guide that switches OEM at runtime without setting legacyCore; not knowing the core build is tied to creation-time options.

Related errors


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