We had compalints from customer that some of the features of extension are not working anymore, upon checking, it seems something with message passing has changed that regresses quite features. These features worked just fine from last 2 years but suddenly broken.
I tried to atleast reproduce one method that we are using actively in our extension but not working in standalone extension too
It is for chrome.runtime.onMessage, exactly as documented for Chrome 144+.
The value returned from an async onMessage listener is always received as undefined in the sender, even though the listener resolves to a concrete value.
Version 145.0.7632.46 (Official Build) (64-bit)
OS: Windows
Manifest.json
{
"manifest_version": 3,
"name": "Async Message Test",
"version": "1.0",
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["https://*/*"],
"js": ["content_script.js"]
}
]
}
background.js
chrome.runtime.onMessage.addListener(async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
return "OK";
});
content_script.js
(async () => {
const response = await chrome.runtime.sendMessage("test");
console.log("response:", response);
})();
Let me know if I have to report this into proper channel but I'm looking if I am doing something wrong to fix this issue in my current production extension or I can report this in proper channel as well, thanks!
async to return a promise:chrome.runtime.onMessage.addListener(async function(message, sender) {
const response = await fetch('https://example.com');
if (!response.ok) {
// rejects the promise returned by `async function`.
throw new Error(`Fetch failed: ${response.status}`);
}
// resolves the promise returned by `async function`.
return {statusCode: response.status};
});Both documentation says otherwise
https://developer.chrome.com/docs/extensions/develop/concepts/messaging
From documentation:
You can also declare a listener asasyncto return a promise:chrome.runtime.onMessage.addListener(async function(message, sender) { const response = await fetch('https://example.com'); if (!response.ok) { // rejects the promise returned by `async function`. throw new Error(`Fetch failed: ${response.status}`); } // resolves the promise returned by `async function`. return {statusCode: response.status}; });On Wed, Feb 11, 2026 at 2:23 PM Daniel MacArthur <d.mac...@everway.com> wrote:your issue is in background.js, as of chrome 144+ you can no long have async in the runtime listener:
background.js
chrome.runtime.onMessage.addListener(async () => {
await new Promise(resolve => setTimeout(resolve, 1000));
return "OK";
});
this would fix your example:
manifest.json
{
"manifest_version": 3,
"name": "Async Message Test",
"version": "1.0",
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["https://*/*"],
"js": ["content_script.js"]
}
]
}
background.js
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
// Return true to signal we will send a response asynchronously
new Promise(resolve => setTimeout(resolve, 1000))
.then(() => {
sendResponse("OK");
})
.catch(error => {
console.error('Error in message listener:', error);
sendResponse({ error: error.message });
});
return true; // Keep channel open for async response
});
content_script.js
(async () => {
try {
const response = await chrome.runtime.sendMessage("test");
console.log("response:", response);
} catch (error) {
console.error("Error sending message:", error);
}
})();