sendMessage and onMessage.addListener works fine in Chrome but not in Firefox

I’m making an extension which have a content script and a background script.
The content script use browser.runtime.sendMessage sends a message to background script and expecting got a reply from background script.

content-script.js
const response = await browser.runtime.sendMessage(…)

background-script.js
browser.runtime.onMessage.addListener((event, sender) => {
// make an ajax request to server and send server’s response back to content script
return Promise(…)
})

These code works on Chrome.
In Firefox(MacOS 11.2.3 Firefox 92.0.1 64 bit), I can see background script received a message and make an ajax request to server and got a response from server,
but content script throws an error:
Error: Could not establish connection. Receiving end does not exist.

I need some helps, thanks.

This usually indicates that the tab that send the message was already closed or that there is no background page that has the onMessage listener. Also note that only one onMessage listener can respond to the message, so if you have multiple the “wrong one” might be responding.

Hi freaktechnik, thank you for your reply!

I can confirm that background script has only one onMessage listener, and has received the message from content script and return a Promise, these codes works properly in Chrome.

@ Doflatango
Can you upload your extension?
Zip your extension, click “Reply” and then the “Upload” button.
It’s the 7th button from the left, an arrow pointing up.

Hi @freaktechnik @hans_squared , after spent a few hours, i found the issue finally.

So, i’m using axios as my http client in background script, and in the background script onMessage listener, i return the entire response which axios returned(include every thing about a request) back to content script, when content script recevicing this response, it throw an error:

Error: Could not establish connection. Receiving end does not exist.

If i just return some fields extracting from the response back to content script, such as response.data, response.headers and response.status, and it works now!

May be the content script have a size limit when recevicing a response, which the size of entire response are too bigger for that after json serialized.
These might consider as an issue due to the size limit is too small for modern applications.

The response object might not be able to be cloned, though I’d expect a different error in that case. Either way, nice catch!

You should always send only simple objects, ideally “JSON compatible types” because the cloning algorithms in browsers (especially Chromium) are pretty bad and it can break easily if you send something slightly complicated.

For example, Chrome can’t even handle Blobs! But usually it throws some error saying that the object cannot be cloned, but not always.

Also, I’m not sure about recursive nested objects. But anyway, the functions will be gone, object instances will be lost (converted to simple objects), Map / Set will be converted to some empty objects, I think… just don’t! :smiley:

I am also getting this error in Firefox only (not in Chrome, and not in Safari although Safari requries a different mechanism for returning responses). In my case, I’m returning the “response” from a “fetch” call. Problem goes away if I change the Response object into a plain object (I’m posting, so all I need to know is #ok and #status).