Stacked stack traces with JS

Consider the below (simplified) file that represents an external API that our project is trying to communicate to:

const Axios = require('axios');

const client = new Axios({ url: 'example.com/api' })

export function getRecords() {
  try {
    return client.get('/records');
  } catch(error) {
    throw error;
  }
}

export function createRecord(name) {
  try {
    return client.post('/records', { name });
  } catch(error) {
    throw error;
  }
}

This module will be required from a parent module where Sentry has been initialized and when either of these functions throws an error, we will submit to Sentry.

The main problem with the above is that in both cases, the stack trace of the error will be the exact same. It will start from inside the axios library where the actual error instance was created (which is valid, as per Node.js documentation). But it makes debugging really really hard.

To overcome this error, we stack errors together. So the above will become:

const Axios = require('axios');
const StackedError = require('../errors');

const client = new Axios({ url: 'example.com/api' })

export function getRecords() {
  try {
    return client.get('/records');
  } catch(error) {
    throw new StackedError(error.message, error);
  }
}

export function createRecord(name) {
  try {
    return client.post('/records', { name });
  } catch(error) {
    throw new StackedError(error.message, error);
  }
}

And what StackedError is doing is to take the stack trace from the original error and concatenate it with the one from the newly created error.

Source of the StackedError is (written in TypeScript):

export default class StackedError extends Error {
  original: any;
  new_stack: any;

  constructor(message: string, error: Error) {
    super(message);

    this.original = error;

    const messageLines = (this.message.match(/\n/g) || []).length + 1;
    
    this.stack = `${(this.stack || '')
      .split('\n')
      .slice(0, messageLines + 1)
      .join('\n')}'\n'${error.stack}`;
  }
}

The above works great and we are able to make sense of our runtime errors, find exactly where the error was thrown and what caused it.

But now Sentry is not able to parse the stack trace.

My question is, do you see a way of making Sentry correctly parse the stack trace?

Do you have some other recommendations to work with JavaScripts’ stack traces?