Message channel closed before a response was received

This error message indicates a problem with communication between the listener and the message channel. The listener sent a response indicating it was ready to receive a message, but the message channel closed before the listener could receive the message.

Solution

In most cases, this occurs when you call chrome.runtime.sendMessage while the popup is not shown. Popups cannot receive messages if they are hidden. You can suppress the error by using () => chrome.runtime.lastError instead of function(response) {}.

Another possible solution would be show the popup in a new window using chrome.windows.create or as a DOM element inside the web page.

Background

This issue is related to cross-origin requests and can be caused by various Chrome extensions. To prevent leaks of sensitive information, web pages are generally not allowed to fetch cross-origin data. Unless a valid CORS header is present in the response, the page's request will fail with an error message.

There was a change in Chrome that introduced this error message.

const char kReceivingEndDoesntExistError[] = // TODO(lazyboy): Test these in service worker implementation. "Could not establish connection. Receiving end does not exist."; +const char kClosedWhileResponsePendingError[] = + "A listener indicated an asynchronous response by returning true, but the " + "message channel closed before a response was received"; } // namespace
async response to runtime.sendMessage. Example code:
// sender chrome.runtime.sendMessage('testMessage');
// receiver chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => { doSomethingWithoutResponding(msg); });

The reason is that sendMessage is now internally promisified, so you can use await with it. However, a byproduct is that when you don't specify a callback yourself, one is added internally to make the call return a Promise. This means that if you don't call sendResponse in onMessage, the API will think you made a mistake by using a callback and not providing a response, and report it as such.

Since the new behavior is very confusing for many developers, a solution might be to stop showing this error when a callback is not specified. However, this might cause confusion for developers who still use callbacks and forget to call sendResponse inside onMessage by mistake, which ideally should still be reported.

If you see your extension causing these errors, inspect all your onMessage listeners closely. Some of them probably need to start returning promises (marking them as async should be sufficient).

Background script

In many cases, the issue you face is the background script. It does not invoke sendResponse() for one or more messages it receives and goes inactive (causing the message channel to close). However, the content script that sent the message is waiting for the response.

In Manifest V3, the Chrome extension platform moves from background pages to service workers. The background script (service worker in MV3) could be going to an inactive state without sending a response back to a message it received from a content script.

Background script:
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { // ... handle message here return true // your error message says you already return true })

The runtime.onMessage event allows you to listen for messages from another part of your extension. Most Manifest V3 APIs can return promises when it makes sense to do so. Reading a response back can be done using callbacks or a promise-based approach.

Method-1 : Content script to read response:
chrome.runtime.sendMessage('ping', (response) => { /* read response */ })
Method-2 : Content script to read response:
chrome.runtime.sendMessage('ping').then(response => { /* read response */ })

So, in order to solve your problem, please check your message senders & handlers. Also, if you are an extension developer, You need to return true when fetching data from cross-origins.

Other solutions:

  1. Try disabled all installed extensions in Chrome then you will get a clear console without errors.

Or

  1. Go to chrome://extensions/, you can just toggle each extension one at a time and see which one is actually triggering this issue.
  2. Once you toggle the extension off, refresh the page where you are seeing the error and wiggle the mouse around, or click. Mouse actions are the things that are throwing errors.

Conclusion

By disabling extensions one by one, you can pinpoint which extension is actually causing the issue and disable it temporarily to resolve the "Uncaught (in promise) Error: A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received" error.