mozilla/pdf.js · error · Error
Worker was destroyed
Error message
Worker was destroyed
What it means
A generic Error in getDocument's startup chain: after worker.promise resolves but before the GetDocRequest is sent, the worker was destroyed (worker.destroyed === true). The whole document load is aborted because there is no live worker to receive the request. This is a lifecycle error, not a data error.
Source
Thrown at src/display/api.js:407
wasmUrl,
hasGPU: false, // Set below.
},
};
const transportParams = {
ownerDocument,
pdfBug,
styleElement,
enableHWA,
loadingParams: {
disableAutoFetch,
enableXfa,
},
};
Promise.all([worker.promise, gpuPromise])
.then(function ([, hasGPU]) {
if (worker.destroyed) {
throw new Error("Worker was destroyed");
}
docParams.evaluatorOptions.hasGPU = hasGPU;
const workerIdPromise = worker.messageHandler.sendWithPromise(
"GetDocRequest",
docParams,
data ? [data.buffer] : null
);
let networkStream;
if (data) {
// The entire PDF was provided, no `networkStream` necessary.
} else if (rangeTransport) {
networkStream = new PDFDataTransportStream({
pdfDataRangeTransport: rangeTransport,
disableRange,
disableStream,View on GitHub (pinned to 5903d58d58)
Solutions
- Track the loading task and only destroy it once you no longer need the document; avoid destroying during load.
- If cancelling is intentional, treat 'Worker was destroyed' as an expected rejection, not a bug.
- Ensure you await any prior task.destroy() before starting a new getDocument that reuses the worker/port.
- Use a separate PDFWorker per concurrent load instead of sharing one that gets torn down.
Example fix
// before
const task = pdfjsLib.getDocument({ url });
setTimeout(() => task.destroy(), 50); // kills worker mid-handshake
// after
let task = pdfjsLib.getDocument({ url });
try {
const doc = await task.promise;
} catch (e) {
if (/Worker was destroyed/.test(e.message)) return; // expected cancel
throw e;
} Defensive patterns
Strategy: try-catch
Validate before calling
// Do not start a load while a destroy is pending on the shared worker.
if (worker.destroyed) {
throw new Error('Refusing to load: worker already destroyed');
} Try / catch
try {
const doc = await loadingTask.promise;
} catch (e) {
if (/Worker was destroyed/.test(e.message)) return null; // expected cancel
throw e;
} Prevention
- Await loadingTask.destroy() before reusing a worker/port.
- Track loading tasks in a single owner so components cannot destroy out of order.
- In SPAs, cancel via a flag instead of destroying during the handshake window.
When it happens
Trigger: Calling loadingTask.destroy() or worker.destroy() during the brief window after worker setup but before GetDocRequest is dispatched; destroying a previously-started loading task and immediately starting a new one reusing the same worker; rapid mount/unmount in a SPA.
Common situations: React/Vue components that tear down before the async load resolves; navigation away from a page mid-load; cancelling a queued load after a timeout.
Related errors
- Loading aborted
- PDFWorker.create - the worker is being destroyed. Please rem
- Worker was destroyed.
- Transport destroyed
- Cannot use more than one PDFWorker per port.
AI-assisted analysis of mozilla/pdf.js@5903d58d58 (2026-08-13).
Data as JSON: /api/errors/b69f847236626af9.
Report an issue: GitHub.