{"record":{"id":"19f19c5474ad226b","repo":"mozilla/pdf.js","slug":"loading-aborted","errorCode":null,"errorMessage":"Loading aborted","messagePattern":"Loading aborted","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/display/api.js","lineNumber":467,"sourceCode":"          throw new Error(\"Worker was destroyed\");\n        }\n\n        const messageHandler = new MessageHandler(docId, workerId, worker.port);\n        const transport = new WorkerTransport(\n          messageHandler,\n          task,\n          networkStream,\n          transportParams,\n          transportFactory,\n          pagesMapper\n        );\n        task._transport = transport;\n\n        if (task.destroyed) {\n          // `destroy()` was called during the worker handshake; the orderly\n          // shutdown (including the \"Terminate\" message) will be issued\n          // through the transport once destroy resumes.\n          throw new Error(\"Loading aborted\");\n        }\n        messageHandler.send(\"Ready\", null);\n      });\n    })\n    .catch(task._capability.reject)\n    .finally(task._setupCapability.resolve);\n\n  return task;\n}\n\n/**\n * @typedef {Object} OnProgressParameters\n * @property {number} loaded - Currently loaded number of bytes.\n * @property {number} total - Total number of bytes in the PDF file.\n * @property {number} percent - Currently loaded percentage, as an integer value\n *   in the [0, 100] range. If `total` is undefined, the percentage is `NaN`.\n */\n","sourceCodeStart":449,"sourceCodeEnd":485,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/src/display/api.js#L449-L485","documentation":"A generic Error thrown after the WorkerTransport is constructed: if task.destroyed is true (destroy() was called during the worker handshake), pdf.js aborts with 'Loading aborted' instead of sending the Ready message. The orderly shutdown (including the Terminate message) is handled later by the transport, so this is a controlled abort of the load promise.","triggerScenarios":"loadingTask.destroy() invoked during the window between worker handshake completion and the Ready send; rapid create/destroy cycles; a component that destroys its task in cleanup while the initial load is still settling.","commonSituations":"SPA route changes, timeout-based cancellation, user cancel button pressed during initial load, double-mount bugs in React StrictMode.","solutions":["If cancellation is intended, catch and swallow 'Loading aborted' as a normal outcome.","Do not call destroy() unless you actually want to cancel; debounce rapid load requests.","Sequence loads: await one task's destroy before starting the next."],"exampleFix":"try {\n  const doc = await loadingTask.promise;\n} catch (e) {\n  if (/Loading aborted|Worker was destroyed/.test(e.message)) return;\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":"if (loadingTask.destroyed) {\n  // do not expect the load to resolve; it will reject with 'Loading aborted'.\n}","typeGuard":null,"tryCatchPattern":"try {\n  const doc = await loadingTask.promise;\n} catch (e) {\n  if (/Loading aborted/.test(e.message)) return; // intentional cancel\n  throw e;\n}","preventionTips":["Treat 'Loading aborted' as a normal outcome of user-initiated cancel.","Debounce rapid load requests so you do not destroy a load mid-handshake.","Sequence loads: await one task's destroy before starting the next."],"tags":["lifecycle","destroy","race-condition","getdocument","loading-task"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}