quasarframework/quasar · error

Failed to send message to "${packet.to}".

Error message

Failed to send message to "${packet.to}".

What it means

#sendPacket is the bridge's core send routine: it calls port.postMessage(packet) on the underlying browser runtime port. If postMessage throws (e.g. the port has been disconnected because the other side closed, or the message isn't serializable), the promise rejects with the underlying error after logging this warning.

Source

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

    if (!this.portList.includes(packet.to)) {
      return Promise.reject(
        `Tried to send message of type "${packet.type}" to "${packet.to}" but there is no such port registered`
      )
    }

    if (port === void 0) {
      return Promise.reject(
        this.#type === 'background'
          ? `Tried to send message of type "${packet.type}" to "${packet.to}" but the port is not available`
          : `Tried to send message of type "${packet.type}" to "${packet.to}" but the port to background is not available to forward through`
      )
    }

    try {
      port.postMessage(packet)
    } catch (err) {
      this.warn(`Failed to send message to "${packet.to}".`, err)
      return Promise.reject(err)
    }

    return Promise.resolve()
  }

  /**
   * @param {{ id?: number, to: string, payload: any, messageType: "event-send" | "event-response", messageProps: any }} param
   */
  #sendMessage({
    id = getRandomId(1_000_000),
    to,
    payload,
    messageType,
    messageProps
  }) {
    if (!Array.isArray(payload)) {
      return this.#sendPacket({

View on GitHub (pinned to 4841521b5f)

Solutions

  1. Listen for port disconnect/onDisconnect and recreate the bridge before sending again
  2. Serialize the payload — send only JSON-cloneable values (no functions, DOM nodes, class instances)
  3. Wrap bridge.send() calls in try/catch (it returns a rejected promise) and retry after reconnection
  4. Check the companion `err` for 'Attempting to use a disconnected port object' to confirm the cause

Example fix

// before
bridge.send('save.data', { save: fn, el: document.body })
// after
try {
  await bridge.send('save.data', { data: JSON.parse(JSON.stringify(state)) })
} catch (err) {
  // recreate bridge/port then retry
}
Defensive patterns

Strategy: try-catch

Validate before calling

// ensure payload is structured-cloneable before sending
function isCloneable(value) {
  try { structuredClone(value); return true } catch { return false }
}

Try / catch

try {
  await bridge.send('my.event', payload)
} catch (err) {
  if (String(err).includes('disconnected port')) {
    await reconnectBridge() // re-open port, then retry
  } else if (!isCloneable(payload)) {
    console.error('Payload not cloneable: strip functions/DOM nodes')
  }
}

Prevention

When it happens

Trigger: Calling bridge.send()/#sendMessage while the receiving context (content script, popup, background) has disconnected; attempting to send a non-cloneable value (function, DOM node) in the packet; posting on a port whose counterpart page was reloaded by hot-reload.

Common situations: Extension service worker restarted in MV3 and stale ports were used; user closed the popup mid-request; dev rebuild reloaded the content script; sending state objects containing functions or class instances.

Related errors


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