{"record":{"id":"9d7fb6d6adfd8415","repo":"mozilla/pdf.js","slug":"the-overlay-is-already-registered","errorCode":null,"errorMessage":"The overlay is already registered.","messagePattern":"The overlay is already registered\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"web/overlay_manager.js","lineNumber":36,"sourceCode":"\n  #active = null;\n\n  get active() {\n    return this.#active;\n  }\n\n  /**\n   * @param {HTMLDialogElement} dialog - The overlay's DOM element.\n   * @param {boolean} [canForceClose] - Indicates if opening the overlay closes\n   *                  an active overlay. The default is `false`.\n   * @returns {Promise} A promise that is resolved when the overlay has been\n   *                    registered.\n   */\n  async register(dialog, canForceClose = false) {\n    if (typeof dialog !== \"object\") {\n      throw new Error(\"Not enough parameters.\");\n    } else if (this.#overlays.has(dialog)) {\n      throw new Error(\"The overlay is already registered.\");\n    }\n    this.#overlays.set(dialog, { canForceClose });\n\n    dialog.addEventListener(\"cancel\", ({ target }) => {\n      if (this.#active === target) {\n        this.#active = null;\n      }\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.\");","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/mozilla/pdf.js/blob/5903d58d58e4dd9ce6ffa3834aea8480f06b4ada/web/overlay_manager.js#L18-L54","documentation":"Thrown by OverlayManager.register when the given dialog element is already present in the internal WeakMap (#overlays.has(dialog) is true). Each overlay must be registered exactly once to attach its cancel-listener and state.","triggerScenarios":"Calling register(dialog) twice with the same HTMLDialogElement reference. Common in apps that re-init UI or call setup routines repeatedly without teardown.","commonSituations":"Re-running viewer initialization, double-binding on a reused dialog element, or calling register from multiple components that share the dialog.","solutions":["Register each dialog only once during initial setup.","Guard with the internal state: check OverlayManager.active or track registration in your own flag before calling register.","Remove duplicate register calls introduced by refactoring or shared utilities."],"exampleFix":"// before\nawait OverlayManager.register(dialog); // called again later -> throws\n\n// after\nif (!overlayRegistered.has(dialog)) {\n  await OverlayManager.register(dialog);\n  overlayRegistered.add(dialog);\n}","handlingStrategy":"validation","validationCode":"const registered = new WeakSet();\nif (!registered.has(dialog)) {\n  await OverlayManager.register(dialog);\n  registered.add(dialog);\n}","typeGuard":null,"tryCatchPattern":"try {\n  await OverlayManager.register(dialog);\n} catch (e) {\n  if (e.message === 'The overlay is already registered.') return; // idempotent\n  throw e;\n}","preventionTips":["Register dialogs once during app init.","Track registration state yourself to avoid double-calls.","Make init idempotent across hot-reloads."],"tags":["overlay","duplicate","state","ui-utils"],"backgroundTag":null,"analyzedSha":"5903d58d58e4dd9ce6ffa3834aea8480f06b4ada","analyzedAt":"2026-08-13T02:28:27.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}