chrome browser extension(MV3) reconnect failure after disconnected

213 views
Skip to first unread message

pullagurla harisha

unread,
Feb 18, 2026, 1:50:02 AMFeb 18
to Chromium Extensions
Dear concerned,
   I have migrated my chrome browser extension from MV2 to MV3
   Implementation: Implemented logic in content script to listen to Disconnect event and try reconnecting to background script(service worker) using chrome.runtime.connect() 
    content-script uses chrome.runtime.connect() to start communication and postMessage() to continue communication with background script.. every 25seconds dummy message is sent as keepalive to keep service worker running

   Issue: Chrome browser unloads the service worker and content-script reconnect(Recreating runtime port using chrome.runtime.connect() ) fails.. Tried reconnecting 5times every 3seconds

  Please suggest if this is chrome browser expected behaviour.. If yes should content-script be reinjected to revive background script or are there any alternate ways to wakeup background script from content-script when reconnect fails.. any help is appreciated 

woxxom

unread,
Feb 18, 2026, 4:36:21 AMFeb 18
to Chromium Extensions, pullagurla harisha
A backgrounded tab's timers may be paused by the browser and only fire once in a minute, so the preferred method is calling any asynchronous chrome API in the service worker itself as noted in the official documentation, but are you sure you need to keep the background script running and if so, why?

pullagurla harisha

unread,
Feb 19, 2026, 7:05:05 AMFeb 19
to Chromium Extensions, woxxom, pullagurla harisha
Hi Woxxom,
 Thanks for your response.
 
I am investigating why chrome.runtime.connect reconnection attempts fail and seeking solutions to reactivate the background script when Chrome has unloaded it for resource management.

Simeon Vincent

unread,
Feb 19, 2026, 3:08:28 PMFeb 19
to Chromium Extensions, harisha.pul...@gmail.com, woxxom
For clarity, when you say "chrome.runtime.connect reconnection attempt," you mean that you're trying to call chrome.runtime.connect() from a content script to create a new connection, not that you're trying to reuse the port from a previous connection, right? I wanted to double check because once a connection is closed, the port is effectively useless.

Based on what you've shared so far, my best guess is that your runtime.onConnect.addListener() call in your background script is registered asynchronously. In order for the browser to know that it needs to start the service worker in response to a given event, the event registration has to occur on initial script execution. 

Simeon (dotproto)
incremental.software

pullagurla harisha

unread,
Feb 23, 2026, 4:44:18 AMFeb 23
to Chromium Extensions, Simeon Vincent, harisha.pul...@gmail.com, woxxom
Hi Simeon, 
  Thanks for your response.
   You are correct I am calling connect to create new connection(new runtime port instance both sides).. disconnect indicates old runtime ports are no longer active
   
    I confirm registration of onConnect event handler is in the beginning of background script

    It is difficult to troubleshoot/debug the root cause of extension being unloaded from log file.....Also its reproducible randomly that too only in few customer machines. 

   Any guidance on methods to find root cause is highly appreciated. Also why is `port.onMessage` callback (in service worker) from `port.postMessage` (in content script) is not able to to reset service worker's 30-second inactivity timer causing chrome to unload it

chrome_ext_service_worker_unload.png


Thanks in advance,
Harisha

Simeon Vincent

unread,
Feb 24, 2026, 3:15:03 PMFeb 24
to pullagurla harisha, Chromium Extensions, woxxom
I don't mean to belabor the point, but when you say the "onConnect event handler is in the beginning of background script," that tells us where it is in the file, not when it occurs. Event listeners have to be registered synchronously. The easiest way to do that is to make sure the event listener registration is a top level statement in your script. If you register an event listener in a callback or after awaiting a promise, it may be too late. See the Migrate to a service worker and  Handle events with service workers docs for more information. 

It might be best if you share the source of your extension so folks here can see exactly what's going on. A link to a public repository is probably the best way to do this.

Also why is `port.onMessage` callback (in service worker) from `port.postMessage` (in content script) is not able to to reset service worker's 30-second inactivity timer causing chrome to unload it

The onMessage event doesn't keep the service worker alive because service workers aren't meant to be persistent. I think it might be better to ask, why you're trying to keep the background alive? If you need a more persistent environment, a few other options may be a better fit such as storage.session, opening an extension page in a new window, or (if appropriate) an offscreen document.

Simeon - @dotproto
incremental.software

pullagurla harisha

unread,
Feb 25, 2026, 12:18:37 AM (14 days ago) Feb 25
to Chromium Extensions, Simeon Vincent, Chromium Extensions, woxxom, pullagurla harisha
Hi Simeon, Woxxom, Everyone,
  Thanks Simeon for providing response.

  1. onConnect registration is happening synchronously and present in the first line of background script impl

}(globalThis.f9softphone, function (BaseExtensionScript, InjectedScriptPort, runtime) {
var parentConstructor = BaseExtensionScript.prototype.constructor;

var ExtensionScript = function() {
parentConstructor.apply(this, arguments);

runtime.onConnect.addListener(function (port) {
port = new InjectedScriptPort(port);

console.info('f9phone communication: connected host', port.tabId());

if (this._onNewConnection) {
this._onNewConnection(port);
}
}.bind(this));
};

ExtensionScript.prototype = new BaseExtensionScript();
ExtensionScript.prototype.constructor = ExtensionScript;

return ExtensionScript;
}));

  2. Could you please confirm whether chrome.storage.onChanged in a service worker wakes up the service worker if it has been unloaded/terminated by the Chrome browser due to inactivity?
      I would also greatly appreciate any links or official documentation that provide a comprehensive list of events that are guaranteed to wake up a service worker

Thanks and Regards,
Harisha

Mythical 5th

unread,
Feb 25, 2026, 7:39:01 AM (13 days ago) Feb 25
to Chromium Extensions, pullagurla harisha, Simeon Vincent, Chromium Extensions, woxxom
Harisha,

Your listener is added within a function, so it's not clear that it will wake up the service worker or run when the service worker wakes up.

Here's an example to investigate the issue:

manifest.json
```json
{
  "name": "Wake Up Service Worker",
  "version": "1",
  "manifest_version": 3,

  "action": {
    "default_popup": "popup.html"
  },

  "permissions": [
    "storage"
  ],

  "background": {
    "service_worker": "sw.js",
    "type": "module"
  }
}
```

popup.html
```html
<script src="popup.js" type="module"></script>
```

popup.js
```js
chrome.storage.local.set({timestamp: Date.now()});
```

sw.js
```js
function addListener()
{
  chrome.storage.onChanged.addListener(logEvent.bind(null, "in-function"));
}

function logEvent(event)
{
  console.log(event);
}

chrome.storage.onChanged.addListener(addListener);
chrome.storage.onChanged.addListener(logEvent.bind(null, "top-level"));
```

When you click the toolbar button once, the console shows "top-level" because of the listener added at the top level (ie. global scope) of the service worker. When the button is clicked again the console will show "top-level" and "in-function" because the listener in the function was added when the service worker first ran. If you wait for the service worker to go to sleep, and then click the toolbar button, the console will only show "top-level". This tells us that the storage listener does wake up a service worker, but it must be added at the top level of the service worker rather than in a function.

Reply all
Reply to author
Forward
0 new messages