Webpack and Capturing Error Events - javascript

I am trying to get the original error on the error event listener. However, when the listener is attached from a different script I get the generic "script error" with no stack trace. My understanding is this occurs for cross-origin scripts. However, all of my scripts live inside of the app bundle created by Webpack.
Example
app.js
window.addEventListener("error", function (errEvt) {
console.log(errEvt, window.myErr);
});
some-file.js
function generateError() {
let foo = {};
try {
foo.bar();
} catch (err) {
window.myErr = err;
throw new Error(err);
}
}
These both get bundled into app.bundle.js.
<script src="app/app.bundle.js"></script>
If I attach the error generator to a document click event then I get the following.
(app.js context) window.myErr --> TypeError: foo.bar is not a function
at errors (eval at <anonymous> (app.bundle.js:45), <anonymous>:37:13)
(app.js context) errEvt --> ErrorEvent {message: "Script error.", filename: "", lineno: 0, colno: 0…}
What's going on? Shouldn't these scripts then be considered same origin (they all "live" in app.bundle.js? Is there any way to get the original error without resorting to manually binding it to the window object in a try / catch?
References
https://blog.sentry.io/2016/05/17/what-is-script-error.html
Get the actual Javascript Error object with window.onerror

Related

dyamically appended javascript file throws; is it possible to catch?

In file2.js I have:
throw new String("oops");
In file1.js I have:
document.head.appendChild(dynamically_created_file_2_script_element);
How can I catch the string thrown in file2.js?
I have tried:
try {
document.head.appendChild(dynamically_created_file_2_script_element);
}
catch(err) { ... }
to no avail. Also, the onerror event listener on dynamically_created_file_1_script_element is of no use here.
Before appending the script, you can add an error listener to the window.
The error event is fired on a Window object when a resource failed to load or couldn't be used — for example if a script has an execution error.
Inside the handler, you can check which resource resulted in the error by looking at the filename property of the event.
window.addEventListener('error', (errorEvent) => {
if (errorEvent.filename.endsWith('file2.js')) {
console.log('Saw error from file2.js:')
console.log(errorEvent.message);
}
});
document.body.appendChild(document.createElement('script')).src = './file2.js';
Note that this can only work if the script is on a live server, and on the same domain. Due to cross-origin restrictions, in other situations, the only info available will be Script error.

Global error handling in Nuxt.js using onerror on other methods

I have a website which uses Nuxt.js. I want to implement global error handling when an error or uncaught error occurs.
I have injected the below script to head and also used it as plugin, but it does not work!
<script>
window.onerror = function (e) {
console.log('### Here I am ###', e)
return true
}
window.addEventListener('error', ...)
</script>

Intercepting browser errors even if wrapped in try catch

So as the title states I would like to be able to intercept all errors that occur on the page. So starting off with the simplest way:
Add an error event listener to window and store the errors as they occur
The problem with this approach is that if the code that is causing the error is wrapped in a try catch block, the error listener never gets triggered.
A partial solution to this issue is to override the Error constructor so that any time code such as throw new Error() is called we can intercept it using our override. This approach works very nicely for user generated errors, this doesn't work for errors that originate in the browser. For example:
const a = ()=> {
const b = {};
console.log(b.c.d) // Uncaught TypeError: Cannot read property 'c' of undefined
}
try {
a()
} catch(err) {
console.log(err)
}
I would like to be able to detect that a TypeError has been thrown. Overriding the TypeError constructor does not work in this case.
Any ideas?
EDIT: The point is to be able to intercept errors that 3rd party scripts wrap with a try catch

How does Sentry track errors?

Do anyone have the Idea of how Sentry intercepts exceptions?
I am only starting to use Sentry. Here is what it suggested to me:
// add this
const Sentry = require('#sentry/node');
Sentry.init({ dsn: 'https://eed343acxxxxxxxxxxx3bb7e3f4bc10#sentry.io/1511416' });
// and call some undefined function
myUndefinedFunction();
So if there is no try .. catch thing, then how does Sentry tracks errors? The source code is open but is pretty hard to grasp.
P.S. I am interested in the internal mechanism of work not in the user instructions.
You simply need to add captureExcepton :
First, init the app
Sentry.init({ dsn: 'https://8ad77012ba2c436aba8a12e0b6cfd46b#sentry.io/1382991' });
Then you need to capture error by doing like this :
function captureError(err){
Sentry.withScope(scope => {
Object.keys(extra).forEach(key => { //Here you can add extra message(optional)
scope.setExtra(key, extra[key]);
});
Sentry.captureException(error); //important
});
}
and you can call this function from anywhere just pass err object
Note : You need to capture this error somewhere either in function or either in try catch. You need to tell sentry to capture this exception
When an error is fired but not caught, the browser will trigger an error event on the window object (see MDN docs for `onerror). Sentry listens for this - here's where in the source code:
https://github.com/getsentry/sentry-javascript/blob/2f365ab86418b7d0bb624bf68fc4084c9bf4691b/packages/utils/src/instrument.ts#L585-L604
In this file you can see (among other things) how Sentry listens for uncaught Promise rejections, using the same approach:
https://github.com/getsentry/sentry-javascript/blob/2f365ab86418b7d0bb624bf68fc4084c9bf4691b/packages/utils/src/instrument.ts#L606-L621
if you have a error, you should send error to sentry, like this:
import * as Sentry from "#sentry/browser";
handleError(error: any): void {
Sentry.captureException(error);
}

catching error event message from firefox

I can't find a way to catch the error message under firefox:
window.addEventListener("error", handleException, false);
...
function handleException(e) {
alert(e);
return false;
}
...
<script>
throw new Error('sdasd');
</script>
This enters very well the handleException method however the e parameter is an error event under firefox and I don't know how to get the associated message.
In chrome for instance, I get either the message through e.message because after the error bubbles up to not being caught, there's an automatic error fired at window level (See this fiddle: the final error is "Uncaught") that contains the original error that I raised manually.
So to have the same behaviour under firefox (if you run the fiddle under firefox you'll see that the message is "undefined") I found a workaround consisting in encapsulating an error raising function to setup a manual "last error" architecture:
function err(I_sText) {
g_lastManualError = new Error(I_sText);
throw g_lastManualError; //this variable is global so I can get the message from anywhere
}
So instead of doing throw new Error(..) I only call err(..). That works, at least for user defined exceptions, which are my biggest concern. In my handler handleException I'm consulting the global variable.
Do you know how I could do otherwise? I'm not happy with this solution.
Thank you,
S.
I modified your code a little as a demo:
function handleException(e) {
console.log(e);
alert(e);
return false;
}
window.addEventListener("error", handleException, false);
try {
throw new Error('sdasd');
}
catch (e) {
console.log(e)
}
console.log('after exception 1');
throw new Error('foo');
console.log('after exception 2');
Running this code (in Firebug) showed me this:
Error: sdasd
[Break On This Error]
Filtered chrome url chrome://firebug/content/console/commandLineExposed.js
comman...osed.js (line 175)
<System>
after exception 1
"Error: foo ` throw new Error('foo');` #14"
If you're trying to catch an error, use try {...} catch { ...}. It looks like you're just binding to an error event, so the exception you're throwing will still propagate up to window and tell the JS engine to halt. Run this code in Chrome, you'll see that you never see "after exception 2", but you will see "after exception 1".
The purpose of exceptions (created by throw) is to stop code execution unless there's code made to handle that particular exception. You can see an example on the MDN page for try-catch
Edit: it just occurred to me that you might be trying to catch a jQuery error event. If this is the case, your event binding is correct but you shouldn't be testing it with throw
Edit 2: I should've noticed this sooner, but you're trying to listen for a DOM error event with window.addEventListener. Error events will not break execution. Exceptions do.
Replace your code throw new Error('sdasd'); with this code:
var customEvent = new CustomEvent('error')
window.dispatchEvent(customEvent);
That should solve your problem. I used the MDN page on custom events as a reference.

Categories