naptha/tesseract.js · error · Error
`worker.detect` requires Legacy model, which was not loaded.
Error message
`worker.detect` requires Legacy model, which was not loaded.
What it means
worker.detect() runs Tesseract's DetectOS, which depends on legacy engine components absent from the LSTM-only core. The guard at src/createWorker.js:179 checks lstmOnlyCore and throws before sending any job to the worker thread. detect() therefore requires a worker built with the full core.
Source
Thrown at src/createWorker.js:179
startJob(createJob({
id: jobId,
action: 'setParameters',
payload: { params },
}))
);
const recognize = async (image, opts = {}, output = {
text: true,
}, jobId) => (
startJob(createJob({
id: jobId,
action: 'recognize',
payload: { image: await loadImage(image), options: opts, output },
}))
);
const detect = async (image, jobId) => {
if (lstmOnlyCore) throw Error('`worker.detect` requires Legacy model, which was not loaded.');
return startJob(createJob({
id: jobId,
action: 'detect',
payload: { image: await loadImage(image) },
}));
};
const terminate = async () => {
if (worker !== null) {
/*
await startJob(createJob({
id: jobId,
action: 'terminate',
}));
*/
terminateWorker(worker);
worker = null;View on GitHub (pinned to a1ca80d9e3)
Solutions
- Create the worker with { legacyCore: true, legacyLang: true } so the legacy engine and language data are available.
- Create the worker with OEM.TESSERACT_ONLY or OEM.TESSERACT_LSTM_COMBINED, which forces legacy core/lang.
- Drop detect() and call recognize() with output.layoutBlocks = true to get layout info from the LSTM engine.
Example fix
// before
const worker = await createWorker('eng'); // LSTM-only
const { data } = await worker.detect(img); // throws
// after
const worker = await createWorker('eng', OEM.TESSERACT_LSTM_COMBINED, { legacyCore: true, legacyLang: true });
const { data } = await worker.detect(img); Defensive patterns
Strategy: validation
Validate before calling
// Track whether the worker was built with legacy support.
const legacyEnabled = options.legacyCore === true || oem === 0 || oem === 2;
async function safeDetect(worker, image, legacyEnabled) {
if (!legacyEnabled) {
throw new Error('detect() needs legacy core; recreate worker with legacyCore:true');
}
return worker.detect(image);
}
const r = await safeDetect(worker, image, legacyEnabled); Type guard
const workerSupportsDetect = (creationOem, options) => creationOem === 0 /* TESSERACT_ONLY */ || creationOem === 2 /* TESSERACT_LSTM_COMBINED */ || options?.legacyCore === true;
Try / catch
try {
await worker.detect(image);
} catch (e) {
if (/Legacy model.*not loaded/i.test(e.message)) {
await worker.terminate();
worker = await createWorker('eng', 2, { legacyCore: true, legacyLang: true });
return worker.detect(image);
}
throw e;
} Prevention
- If you may call detect(), create the worker with OEM.TESSERACT_LSTM_COMBINED and legacyCore/legacyLang from the start.
- Prefer recognize() with output.layoutBlocks for layout info when you cannot afford the legacy build size.
- Document per worker instance whether detect() is available, derived from its creation OEM/options.
When it happens
Trigger: Calling worker.detect(image) on a worker created with default options (OEM.LSTM_ONLY, no legacyCore flag).
Common situations: Using defaults and wanting orientation/script detection; copying detect() from docs without reading the legacy-core requirement; wanting OSD on a minimal-size build.
Related errors
AI-assisted analysis of naptha/tesseract.js@a1ca80d9e3 (2026-08-13).
Data as JSON: /api/errors/86c0309514e889f6.
Report an issue: GitHub.