This happens because of asynchronous code. Here is a repl that will help you understand. The below is standalone code, so you can play with it to understand. Uncommenting each of the errors bellow will trigger an exception differently.
// Mock of chrome.tabs.get, for illustration purposes
function chromeTabsGet(tabId, callback) {
// v----------------- This error will be caught
// throw Error();
setTimeout(() => {
// v------------- This error will not (just like the one you see)
throw Error()
callback({url: 2})
}, 0)
}
try
{
chromeTabsGet(0, function(tab) //this is line 484 where exception happens
{
var tabUrl = '';
try
{
tabUrl = tab.url;
}
catch(e)
{
// Failed to get tab URL -- mute it
}
if(tabUrl)
{
// Process it
}
});
}
catch(e)
{
// Failed to get tab for 'nTabID' -- mute it
}
As you see, chrome.tabs.get
(illustrated as chromeTabsGet
here) can throw in two ways. If it throws inside the function itself, then you will catch it right away in your outer-most try-catch. However, if the function dispatches one (or more) asynchronous events, then those events go out of the main control flow, are put inside the event loop queue and are dispatched later. For this reason, they are not run inside your try-catch anymore, because that code already finished executing.
One way to go around this is to use await
and async
instead of callbacks, but browsers do not support it yet (can do that in Node or by using Babel though)
As @wOxxOm suggested, for your particular problem, have a look at Unchecked runtime.lastError when using Chrome API
Edit: I am in fact a bit outdated on my browser knowledge. Most modern browsers do in fact support await
and async
, and in your case, you already use chrome, so you're good.