Put `Error.cause` in error data with `ExtraErrorData` integration
Is there an existing issue for this?
- [X] I have checked for existing issues https://github.com/getsentry/sentry-javascript/issues
- [X] I have reviewed the documentation https://docs.sentry.io/
- [X] I am using the latest SDK release https://github.com/getsentry/sentry-javascript/releases
How do you use Sentry?
Sentry Saas (sentry.io)
Which package are you using?
@sentry/node
SDK Version
7.36.0
SDK Setup
See below.
Steps to Reproduce
Given running the following script with node index.mjs:
// index.mjs
import Sentry from '@sentry/node';
import { ExtraErrorData } from '@sentry/integrations';
Sentry.init({
dsn: process.env.SENTRY_DSN,
integrations: [
new ExtraErrorData(),
],
});
function lower() {
const err = new Error('lower');
err.lowerFoo = 'baz';
throw err;
}
function upper() {
try {
lower();
} catch (lowerErr) {
const err = new Error('upper', { cause: lowerErr });
err.upperFoo = 'bar';
console.error(err);
throw err;
}
}
upper();
Expected Result
As the errors are linked, I'd expect to see the extra data for both.
Actual Result
I can only see extra data for the upper error:
, although lowerFoo: 'baz' shows in the console.log() breadcrumb:
Hi, thanks for writing in! The reason the integration currently doesn't support cause is because that field is not enumerable and we're simply iterating over all of the fields when adding the extra data. We could probably add a case for cause with not too much effort. Currently, though, I am not sure when we will get to it but you could open a PR to speed up the process!
In the meanwhile I replaced it with a beforeSend handler where I use something like
function getExtraData(err) {
const result = {};
let currentErr = err;
let keyPrefix = '';
let empty = true;
do {
for (const key of Object.keys(currentErr)) {
result[`${keyPrefix}${key}`] = currentErr[key];
empty = false;
}
currentErr = currentErr.cause;
keyPrefix += 'cause.';
} while (currentErr);
return empty ? undefined : result;
}
which returns
{
upperFoo: 'bar',
'cause.lowerFoo': 'baz'
}
Another related small nit is that when the error has no extra data, an empty object {} is still added to contexts, showing an empty section in the UI: