"A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received", What does that mean?

Viewed 50220

I'm working on a React application and I use some npm modules, one of which I had to build myself. (my NPM package: https://www.npmjs.com/package/modale-react-rm).

It is a simple modal that opens and closes with a useState().

After importing my package, I have an error in my console that appears suddenly after a few seconds without performing any actions.


Uncaught (in promise)                                                                  localhost/:1

    >{message: 'A listener indicated an asynchronous response by r…age channel closed before a response was received'}
         message: "A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received"
        >[[Prototype]]: Object
             >constructor: ƒ ()
             >[[Prototype]]: Object

       /* sometimes there are specific elements in addition but I could not check when they appear and when not */

            Promise.then (asynchrone)       
            (anonyme)              @content_script_bundle.js:108
            handleNewFeatures      @content_script_bundle.js:101
            handleUpdatedNodes     @content_script_bundle.js:101
            (anonyme)              @content_script_bundle.js:101
            childlist(asynchrone)
            0                      @purplebox.js:1
            (anonyme)              @purplebox.js:1
            v                      @purplebox.js:1

Error in the console img

It doesn't block my pages, nor does it prevent the proper functioning of its features, but it's an error and I think it should be fixed and maybe help other people who have the same problem.

I specify that I do not make any async request in this project. Everything is local and the few data I use are directly imported in raw. I don't know where Purplebox.js comes from as well.

4 Answers

This issue is a cross-origin request issue and it is caused by various Chrome Extensions. I had this too in my Angular app and after testing it in the incognito mode, the error didn't show up anymore.

More infos: Google Forum

/Edit: If you are an extension developer coming here: You need to return true when fetching data from cross-origins. More info: Chromium Project

In my case, it is caused by Ghostery extension, if this error appears in your local host, you need to add it to the trusted sites list of Ghostery and the error will be gone.

enter image description here

It has been discussed in the webextension-polyfill library, which is used by many extensions (including Ghostery). There was a recent change in Chrome that introduced to the error message.

For projects that are using the polyfill, I would expect the warning to go away if a fix is merged. Note that the polyfill library is used, since only Firefox implements the new promised-based runtime.onMessage, while Chrome still enforces the original callback-style API.

Note that there is an open pull request in the webextension-polyfill library already. It has not been merged, but according to my tests, it solves the problem. So, if you need a quick fix for a project that uses the library internally, you can manually apply the patch with patch-package. For instance, this is how such a change would look like in Ghostery.

The background script (service worker in MV3) could be going to inactive state without sending a response back to a message it received from a content script.

Example:

Background script:

chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
  // ... handle message
  return true // Error message says you already return true
})

Most MV3 APIs are asynchronous and can return promises when it makes sense to do so. (In some cases, like event listeners (e.g.: chrome.tabs.onRemoved), returning a promise wouldn't make sense). Reading a response back however can be done using callbacks or promise-style.

Content script: method 1 to read response:

chrome.runtime.sendMessage('ping', (response) => { /* read response */ })

Content script: method 2 to read response:

chrome.runtime.sendMessage('ping').then(response => { /* read response */ })

The issue you are facing is this: background script does not invoke sendResponse() for one/more messages it received and went inactive (causing the message channel to close). However, the content script that sent the message is waiting for the response.

Please check your message senders & handlers.

Related