PSA: Change to onMessageExternal asynchronous responses

192 views
Skip to first unread message

Justin Lulejian

unread,
Apr 27, 2026, 1:41:42 PMApr 27
to Chromium Extensions

Dear Chromium Extension Developers,


TL;DR: If your extension uses runtime.onMessageExternal for asynchronous responses, you must now explicitly return true; to prevent the “The message port closed before a response was received.” error in Chromium 145.0.7614.0 and later.


As part of recent messaging changes, we identified and fixed a bug in the onMessageExternal listener that was not behaving per API documentation. Although this was mentioned in the original thread, we want to ensure wider visibility.


The runtime.onMessageExternal listener previously kept the message channel open even without explicitly returning true, allowing asynchronous responses without error. After the fix, developers must* explicitly return true; from the listener to send an asynchronous response and prevent a “The message port closed before a response was received.” error.


Prior to the fix, this example worked without return true;:

// background.js

function onMessageExternalListener(message, sender, sendResponse) {

  setTimeout(() => {

    sendResponse('pong');

  }, 100);

  // Listener should `return true;` but actually didn't need to.

}

chrome.runtime.onMessage.addListener(onMessageExternalListener);


After the fix, return true; is required:


// background.js

function onMessageExternalListener(message, sender, sendResponse) {

  setTimeout(() => {

    sendResponse('pong');

  }, 100);

  return true;

}

chrome.runtime.onMessage.addListener(onMessageExternalListener);


We apologize for any unexpected errors or inconvenience this may have caused. In the future, we will ensure API changes like this are announced more explicitly to give extension developers ample time to adapt.


Thank you,

Justin, on behalf of the Chromium Extensions Team

*: As of Chrome 146 you may also return a Promise to indicate an asynchronous response.

Pavel Aronovich

unread,
Apr 28, 2026, 11:06:36 AMApr 28
to Chromium Extensions, Justin Lulejian

Please tell me, is this a possible call option (without return true;)?


// background.js

function onMessageExternalListener(message, sender, sendResponse) {

  setTimeout(() => {

// do the work

  }, 100 );

  sendResponse();

}

chrome.runtime.onMessage.addListener(onMessageExternalListener);


понедельник, 27 апреля 2026 г. в 20:41:42 UTC+3, Justin Lulejian:

Justin Lulejian

unread,
Apr 29, 2026, 5:05:14 PMApr 29
to Chromium Extensions, Pavel Aronovich, Justin Lulejian
Hi Pavel!

If, in your example, sendResponse(); is influenced on what happens in // do the work then you'll want to do:


// background.js

function onMessageExternalListener(message, sender, sendResponse) {

  setTimeout(() => {

// do the work

sendResponse();

  }, 100 );

  return true;

}

chrome.runtime.onMessage.addListener(onMessageExternalListener);


But if sendResponse(); isn't influenced by what happens in // do the work then your example is an option. // do the work would, for the most part*, run after the message sender has received the response from sendResponse();.

Best regards,
Justin
Reply all
Reply to author
Forward
0 new messages