4

I want to copy Javascript Error without reference.

Example:

const error1 = new Error('error1');
const error2 = error1;

error2.message = 'error2';

console.log(error1);
console.log(error2);

Output:

Error: error2
    at evalmachine.<anonymous>:1:16
    at Script.runInContext (vm.js:133:20)
    at Object.runInContext (vm.js:311:6)
    at evaluate (/run_dir/repl.js:133:14)
    at ReadStream.<anonymous> (/run_dir/repl.js:116:5)
    at ReadStream.emit (events.js:198:13)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at ReadStream.Readable.push (_stream_readable.js:224:10)
    at lazyFs.read (internal/fs/streams.js:181:12)

Error: error2
    at evalmachine.<anonymous>:1:16
    at Script.runInContext (vm.js:133:20)
    at Object.runInContext (vm.js:311:6)
    at evaluate (/run_dir/repl.js:133:14)
    at ReadStream.<anonymous> (/run_dir/repl.js:116:5)
    at ReadStream.emit (events.js:198:13)
    at addChunk (_stream_readable.js:288:12)
    at readableAddChunk (_stream_readable.js:269:11)
    at ReadStream.Readable.push (_stream_readable.js:224:10)
    at lazyFs.read (internal/fs/streams.js:181:12)

When i change error2 then error1 will also change. then I tried lodash clone feature. But unfortunately it instead returns an object, not an instance of Error. is there a way so that I can copy an Error without reference and return an instanceof Error without changing stack or other default properties?

Laode Muhammad Al Fatih
  • 3,994
  • 1
  • 18
  • 32

2 Answers2

4

You can try entering some important properties manually:

const error1 = new Error('error1');
const error2 = new error1.constructor(error1.message);

if (error1.stack) {
  error2.stack = error1.stack;
}

if (error1.code) {
  error2.code = error1.code;
}

if (error1.errno) {
  error2.errno = error1.errno;
}

if (error1.syscall) {
  error2.syscall = error1.syscall;
}

error2.message = 'error2';

console.log(error1);
console.log(error2);
1

If you insist on having separate copies of the error, I think your best bet is to create a new error and copy over the properties you want to preserve:

function copyError(err, newMessage) {
    var newErr = new Error(newMessage);

    newErr.stack = err.stack;
    // copy other properties
}

var newErr = copyError(e, "New message");

However, I don't think is such a great approach.

Another option would be to do something like what .NET does - create a new error and place the original error on a property of that error:

var newErr = new Error("New message");
newErr.innerError = originalError;

The drawback here is that anything inspecting these errors would need to check for the presence of an .innerError property and use it accordingly.

JLRishe
  • 99,490
  • 19
  • 131
  • 169