matrix-public-archive/server/lib/errors/rethrown-error.js

49 lines
1.7 KiB
JavaScript

'use strict';
const ExtendedError = require('./extended-error');
// A way to create a new error with a custom message but keep the stack trace of
// the original error. Useful to give more context and why the action was tried
// in the first place.
//
// For example, if you get a generic EACCES disk error of a certain file, you
// want to know why and what context the disk was trying to be read. A
// stack-trace is not human digestable and only gives the where in the code.
// What I actually need to know is that I was trying to read the `ratelimit` key
// from the config when this error occured.
//
// `new RethrownError('Failed to get the ratelimit key from the config', originalError)` (failed to read the disk)
//
// via https://stackoverflow.com/a/42755876/796832
class RethrownError extends ExtendedError {
constructor(message, error) {
super(message);
if (!error) throw new Error('RethrownError requires a message and error');
this.original = error;
this.originalStack = this.stack;
// The number of lines that make up the message itself. We count this by the
// number of `\n` and `+ 1` for the first line because it doesn't start with
// new line.
const messageLines = (this.message.match(/\n/g) || []).length + 1;
const indentedOriginalError = error.stack
.split(/\r?\n/)
.map((line) => ` ${line}`)
.join('\n');
this.stack =
this.stack
.split('\n')
// We use `+ 1` here so that we include the first line of the stack to
// people know where the error was thrown from.
.slice(0, messageLines + 1)
.join('\n') +
'\n' +
' --- Original Error ---\n' +
indentedOriginalError;
}
}
module.exports = RethrownError;