quasarframework/quasar · warning

Failed to inform "${portName}" about the port list.

Error message

Failed to inform "${portName}" about the port list.

What it means

The background side of the Quasar BEX bridge, when the set of connected ports changes (#onPortChange), notifies affected ports about the new port list. If the message to a specific port fails to deliver, the promise rejection is logged with this warning naming the port. It typically means the target content script/iframe port closed just as the list update was sent.

Source

Thrown at app-vite/exports/bex/private/bex-bridge.js:475

  /**
   * Should be used only by the background script
   * @param {{ added?: string } | { removed?: string }} reason
   */
  #onPortChange(reason) {
    this.portList = Object.keys(this.portMap)
    this.#notifyPortWaiters()
    const list = ['background', ...this.portList]

    for (const portName of this.portList) {
      this.send({
        event: '@quasar:ports',
        to: portName,
        payload: {
          portList: list.filter(name => name !== portName),
          ...reason
        }
      }).catch(err => {
        this.warn(`Failed to inform "${portName}" about the port list.`, err)
      })
    }
  }

  /**
   * Should be used only by the background script.
   *
   * The clients cannot be reached through ports (none are available on a
   * fresh background script start), so one-off runtime messages are used.
   */
  async #revivePortClients() {
    // reach the app (popup / devtools / options / extension pages)
    runtime.sendMessage(reviveSignature).catch(() => {
      // no app page is listening
    })

    if (tabs === void 0) return

View on GitHub (pinned to 4841521b5f)

Solutions

  1. Ignore it if transient — it usually means the target port was already gone; the portList update is moot for a dead port.
  2. Ensure content scripts properly disconnect/cleanup ports on beforeunload or pagehide.
  3. Check that the named port's receiving side actually listens for the portList payload and doesn't throw while processing it.
  4. Reopen/reload the affected page so it reconnects and receives the current port list.
Defensive patterns

Strategy: try-catch

Validate before calling

// before sending to a port, verify it is still open
function isPortOpen(port: chrome.runtime.Port | undefined): boolean {
  return port !== undefined // closed ports throw on postMessage
}

Type guard

function isPortAlive(port: chrome.runtime.Port | null): port is chrome.runtime.Port {
  return port != null && typeof port.postMessage === 'function'
}

Try / catch

try {
  await bridge.send({ to: portName, payload: { portList } })
} catch (err) {
  // target port already gone — safe to ignore or prune it from the list
  prunePort(portName)
}

Prevention

When it happens

Trigger: A port (content script, options/popup page) disconnects or is destroyed while the background iterates the port list in #onPortChange and attempts to send it the updated list via bridge messaging; the send promise rejects (port closed, target page unloaded).

Common situations: User closes a tab or popup mid-handshake; page navigates away while ports are being re-broadcast; multiple frames connect/disconnect rapidly during hot reload in BEX dev mode.

Related errors


AI-assisted analysis of quasarframework/quasar@4841521b5f (2026-08-30). Data as JSON: /api/errors/a49ad1574e7820c8. Report an issue: GitHub.