Firefox webextension Error: Could not establish connection. Receiving end does not exist

21,442

Solution 1

You get the error:

Error: Could not establish connection. Receiving end does not exist.

when you attempt to communicate (e.g. tabs.sendMessage(), tabs.connect()) to a tab where a content script is not listening for messages. This includes times when a content script does not exist in the tab.

You can not inject content scripts into about:* URLs

For your issue, you are getting this error because no content script is injected in the tab. By the time you are trying to send the message, in a main_frame webRequest.onErrorOccurred event, the URL for the tab is already about:neterror?[much more, including the URL where the error occurred]. You can not inject content scripts into about:* URLs. Thus, there is no content script in the tab listening for your message.

Specifically, you have used the <all_urls> match pattern in your manifest.json content_scripts entry. <all_urls> matches:

The special value "<all_urls>" matches all URLs under any of the supported schemes: that is, "http", "https", "file", "ftp", "app".

It does not match about:* URLs.

For a bit more discussion of the URL used when Firefox gets a webRequest.onErrorOccurred event in a main_frame, see "Injecting into navigation error page gets: Error: No window matching {“matchesHost”:[“”]}"

Solution 2

For extension developers: If you reload your extension (as a normal part of the development loop) it severs all connections to content scripts.

You must remember to also reload the page for the content script to re-listen correctly.

Solution 3

I also had this same error.

My problem and solution was different but I'm adding it in case it helps.

In my case my content.js script initially did not have a browser.runtime.onMessage.addListener() function (FireFox).

When I later added this listener to the content.js script I did not reload the temporary extension in the "about:debugging" page in FireFox. I got the above error.

After clicking "reload" in the "about:debugging" tab the content script received the message.

Solution 4

I desided same task in next way:

I was making the context menu and have a like problem.

browser.contextMenus.onClicked.addListener((info, tab) => {
       if (info.menuItemId === "mymenu") {
       // some code
       browser.tabs.sendMessage(tabs[0].id, {greeting: "Hi from background script"});
       }
        });

I get error:

Could not establish connection. Receiving end does not exist

I add a function and a listener:

browser.contextMenus.onClicked.addListener((info, tab) => {
       if (info.menuItemId === "mymenu") {
       // some code
       browser.tabs.sendMessage(tabs[0].id, {greeting: "Hi from background script"});
       }
        });
   // -----function and Listener ------
   function connectToContent() {
      browser.tabs.query({ currentWindow: true, active: true
      }).then((tabs) => {
       browser.tabs.sendMessage(tabs[0].id, {greeting: "Activate Tab"});
       });
    }

    browser.tabs.onActivated.addListener(connectToContent);

Now it is working.browser.tabs.onActivated.addListener does and keeps in connect.

Share:
21,442

Related videos on Youtube

user6875880
Author by

user6875880

Updated on July 09, 2022

Comments

  • user6875880
    user6875880 almost 2 years

    I am trying to send a variable from a background script to a content script that is associated with an HTML page. The content script updates the HTML content with the variable received from the background script.

    The problem is that I am getting this error message:

    Error: Could not establish connection. Receiving end does not exist.
    

    The background script main.js:

    var target = "<all_urls>";
    function logError(responseDetails) {
      errorTab = responseDetails.tabId;
      console.log("Error tab: "+errorTab);
    
      errorURL = responseDetails.url;
      console.log("Error URL: "+errorURL);
    
      //send errorURL variable to content script
      var sending = browser.tabs.sendMessage(errorTab, {url: errorURL})
        .then(response => {
          console.log("Message from the content script:");
          console.log(response.response);
        }).catch(onError);
    
      //direct to HTML page
      browser.tabs.update(errorTab,{url: "data/error.html"});
    }//end function
    
    browser.webRequest.onErrorOccurred.addListener(
      logError,
      {urls: [target],
      types: ["main_frame"]}
    );
    

    The error.html is:

    <html>
    <head>
      <meta charset="UTF-8">
    </head>
    <body>
      The error received is <span id="error-id"></span>
      <script src="content-script.js"></script>
    </body>
    </html>
    

    The content-script.js:

    //listen to errorURL from the background script.
    browser.runtime.onMessage.addListener(request => {
      console.log("Message from the background script:");
      console.log(request.url);
      return Promise.resolve({response: "url received"});
    }); //end onMessage.addListener
    
    //update the HTML <span> tag with the error
    document.getElementById("error-id").innerHTML = request.url;
    

    The manifest.json:

    {
      "manifest_version": 2,
      "name": "test",
      "version": "1.0",
      "background": {
        "scripts": ["main.js"]
      },
    
      "content_scripts": [
        {
          "matches": ["<all_urls>"],
          "js": ["webextension/data/content-script.js"]
        }
      ],
    
      "permissions": [
        "<all_urls>",
        "activeTab",
        "tabs",
        "storage",
        "webRequest"
      ]
    }
    
  • user6875880
    user6875880 almost 7 years
    is there any alternatives to achieve customized error page so that I send the error id I get from the background script to my HTML content script? I could update the tab content with a customized HTML. This HTML contains a content script. Some functions do work (like listening to a button click) but I need to send the error data to my HTML. What can I do?
  • Makyen
    Makyen almost 7 years
    @user6875880, As I've mentioned elsewhere, you can't run content scripts in HTML pages sourced from within your extension. You can run normal JavaScript by including it in the page using an HTML <script> tag. Such scripts exist in the background context. If you want to communicate from your background script to/from that script, then you can use any of the methods I describe in: Communicate between scripts in the background context (background script, browser action, page action, options page, etc.)
  • user6875880
    user6875880 almost 7 years
    That's what I am doing. If you look at my HTML, I have src="content-script.js". So, all what I need is to remove that from the manifest content script?? Then, can I send the error code from the background to the HTML's script (the HTML is shown in the error tab using browser.tabs.update(errorTab,{url: "data/error.html"}); ??
  • Makyen
    Makyen almost 7 years
    You certainly should remove it from your manifest.json content_scripts. But, as described in the link I provided, you need to use runtime.sendMessage() (used for destinations that are in the background context) not tabs.sendMessage() (used for destinations that are content scripts). However, given that there is a delay between when you call tabs.update() and when the HTML page and JavaScript are actually loaded and operational, you will probably want to use one of the methods which allows you to pull the data into the HTML page, rather than push it there from the background page.
  • user6875880
    user6875880 almost 7 years
    Thanks. Reference to your last reply: you will probably want to use one of the methods which allows you to pull the data into the HTML page, rather than push it there from the background page. Can you specify the method that allow me to pull the data? or link for an example or so. My apology, I'm not getting what you mean.
  • Makyen
    Makyen almost 7 years
    @user6875880, You can store it in storage.local, just in a normal variable, or have a function in the background page that returns the data. Any of those possibilities are directly usable by the script in your HTML page. Alternately, have your HTML script send a message requesting the data, with the data in the response. The point is that it is much easier for the HTML script to know when it is ready to get the data than for the background page to know when the HTML page is ready to receive it.
  • user6875880
    user6875880 almost 7 years
    if the extension already have a storage for other data. Can I create another storage for the errors? Can one extension has two storage?
  • Makyen
    Makyen almost 7 years
    You can create as many key/value pairs in storage.local as you desire. However, storing huge amounts of data is discouraged due to performance issues.
  • john ktejik
    john ktejik almost 6 years
    so how do you check if something is listening?
  • Makyen
    Makyen almost 6 years
    @johnktejik The only way is to try to send something. If you get the error discussed here, then there isn't anything listening
  • john ktejik
    john ktejik about 4 years
    @Makyen Do you know how do I catch the error? try-catch doesn't seem to be working, maybe because its an asyncronous call?
  • Makyen
    Makyen about 4 years
    @johnktejik You can catch the error just like any other asynchronous error. What that looks like exactly depends on if you're using the chrome.* or browser.* namespace.