onMessage.addListener doesn’t always receive messages from sendMessage in google chrome extension

I communicate between my content script and my background script using chrome.runtime.onMessage.addListener to receive the message on the front in my content.js, and I send messages using chrome.tabs.sendMessage in the background.js script.

On the content.js script, at the start of the file, I have this:

chrome.runtime.onMessage.addListener((msg, sender) => {
  if (msg.command !== 'log') {
    console.log(msg);
  }

  // First, validate the message's structure.
  if (msg.command === 'Browse Startups') {
    // reset the list of startups browsed
    chrome.storage.local.set({'done': []}, function() {
      console.log('Startups Reset');
      chrome.runtime.sendMessage({'action': 'reset'});
    });
    browseStartups();
    return true;
  } else if ((msg.command === 'Check Startup')) {
    shouldStartupBeDone(msg.startup);
    return true;
  } else if ((msg.command === 'Do Startup')) {
    doStartupProfile(msg.url, msg.key, msg.total);
    return true;
  } else if ((msg.command === 'Do Teammate')) {
    doTeammateProfile(msg.startup, msg.teammate);
    return true;
  } else if ((msg.command === 'Save Startup')) {
    saveStartupProfile(msg.startup);
    return true;
  } else {
    console.log('ERROR: this command does not exist');
    return true;
  }
});

and on the background script I do this:

function startDoing(startup, tabId, key, total) {
    console.log('startDoing');
    chrome.tabs.sendMessage(tabId, { command: 'Do Startup', url: startup.url, key: key, total: total });
}

this function is called after the page finished loading like this:

chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
    if (changeInfo.status == 'complete' && tab.active) {
        chrome.storage.local.get(['nextAction', 'startups', 'key', 'teammate', 'startup'], (request) => {
            console.log(request);

            chrome.storage.local.set({ nextAction: null }, () => {
                if (request.startups !== undefined && request.nextAction !== null) {
                    console.log('start');
                    setTimeout(() => {
                        startDoing(request.startups[request.key], tabId, request.key, request.startups.length);
                    }, 7000);
                }
            });
        });
    }
});

From the logs, I can see that when the page is loaded, my background script sends the message to the front, but the front does not receive it and nothing happens, the DoStartup function does not work and my script then breaks.

It does not happen all the time, maybe 1% of the time, but it’s enough to break everything.

Do you know why it happens? Is it the best way to launch a specific content.js script after the page finishes loading?

Here is my manifest:

{
    "manifest_version": 3,
    "name": "My App",
    "short_name": "My App",
    "description": "My App",
    "version": "1.0",
    "action": {
        "default_icon": "icon.png",
        "default_title": "My App",
        "default_popup": "popup/popup.html"
    },
    "icons": { 
        "16": "icon.png",
        "48": "icon.png",
        "128": "icon.png" 
    },
    "permissions": [
        "tabs",
        "activeTab",
        "cookies",
        "storage",
        "webNavigation"
    ],
    "background": {
        "service_worker": "background/background.js"
    },
    "content_scripts": [{
        "matches": [
            "http://*/*",
            "https://*/*"
        ],
        "js": [
            "vendors/jquery.min.js",
            "content/content.js"
        ]
    }]
}