{"record":{"id":"7f471139bc0aa869","repo":"mozilla/pdf.js","slug":"another-overlay-is-currently-active","errorCode":null,"errorMessage":"Another overlay is currently active.","messagePattern":"Another overlay is currently active\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"web/overlay_manager.js","lineNumber":61,"sourceCode":"      }\n    });\n  }\n\n  /**\n   * @param {HTMLDialogElement} dialog - The overlay's DOM element.\n   * @returns {Promise} A promise that is resolved when the overlay has been\n   *                    opened.\n   */\n  async open(dialog) {\n    if (!this.#overlays.has(dialog)) {\n      throw new Error(\"The overlay does not exist.\");\n    } else if (this.#active) {\n      if (this.#active === dialog) {\n        throw new Error(\"The overlay is already active.\");\n      } else if (this.#overlays.get(dialog).canForceClose) {\n        await this.close();\n      } else {\n        throw new Error(\"Another overlay is currently active.\");\n      }\n    }\n    this.#active = dialog;\n    dialog.showModal();\n  }\n\n  /**\n   * @param {HTMLDialogElement} dialog - The overlay's DOM element.\n   * @returns {Promise} A promise that is resolved when the overlay has been\n   *                    closed.\n   */\n  async close(dialog = this.#active) {\n    if (!this.#overlays.has(dialog)) {\n      throw new Error(\"The overlay does not exist.\");\n    } else if (!this.#active) {\n      throw new Error(\"The overlay is currently not active.\");\n    } else if (this.#active !== dialog) {\n      throw new Error(\"Another overlay is currently active.\");","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/web/overlay_manager.js#L43-L79","documentation":"Thrown by OverlayManager.open when another overlay is currently active and the requested dialog was registered without canForceClose=true. The manager enforces single-active-modal semantics; non-force-close dialogs cannot preempt an active one.","triggerScenarios":"Calling open(dialogB) while dialogA is active, where dialogB was registered with register(dialogB) (canForceClose defaults to false).","commonSituations":"Two overlapping dialogs (e.g. password prompt open while trying to open the print dialog) where the second was not flagged canForceClose.","solutions":["Close the active overlay first: await OverlayManager.close(); then open the new one.","Register the new dialog with canForceClose=true if it should preempt: register(dialog, true).","Use closeIfActive to dismiss the active dialog before opening another."],"exampleFix":"// before\nawait OverlayManager.register(dialogB); // canForceClose=false\nawait OverlayManager.open(dialogB); // throws if A active\n\n// after\nawait OverlayManager.register(dialogB, /* canForceClose = */ true);\nawait OverlayManager.open(dialogB);","handlingStrategy":"validation","validationCode":"if (OverlayManager.active && OverlayManager.active !== dialog) {\n  await OverlayManager.close();\n}\nawait OverlayManager.open(dialog);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Register force-closeable dialogs that may preempt others.","Close the active overlay before opening a new one.","Design UI so overlapping modals are intentional."],"tags":["overlay","concurrency","state","ui-utils"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}