Browser.downloads undefined in background script

For an extension, I’m trying to use browser.downloads in a background script like this:

browser.tabs.executeScript(tabId, {file: "foo.js"}).then(
  function (info) {{
      url: info.url,

This fails with browser.downloads undefined. From a post in this forum regarding browser.downloads undefined I’ve learned that I cannot use browser.downloads in content scripts, but why does this restriction apply to my case?

And what would be the correct way to do this? The post suggests using a background script, which I’m already doing.

Works for me…

This is … strange. Maybe I abstracted too much? How about this code?

async function foo() {
    for (var i = 0; i < count; ++i) {
        let tabs = await browser.tabs.query({currentWindow: true, index: i});
        let info = await browser.tabs.executeScript(tabId, {file: "foo.js"});
        bar(tabs, info);

async function bar(tabs, info) {{
        url: info.url,

yields Uncaught (in promise) TypeError: browser.downloads is undefined.

1 Like

EDIT: There’s an even more exhaustive call stack:

TypeError: browser.downloads is undefined
fun3 moz-extension://123/file.js:68
fun2 moz-extension://123/file.js:49
fun1/< moz-extension://123/file.js:13
fun1 moz-extension://123/file.js:10

Maybe you are missing downloads permission in your manifest file?

Thanks for your suggestion, that was indeed the case. My apologies, I totally missed that permission requirement in the MDN docs.

But I also didn’t think that a missing permission would result in something being undefined rather than rejected or forbidden.

Yeah, it’s a bit strange but this is how all permissions works.
So, if you don’t see some API, it usually means you don’t have the permission or the API is not available in the browser or the API is not available in the current context (like in a content script).