Description
Is your feature request related to a problem? Please describe.
I'm using Worker Threads. When the thread crashes with a custom error it is not properly serialized. The following demonstrates the difference (using postMessage
, the result is the same as with the error
event). I'm using verror
because it's very popular library, but this applies to everything that is not a native Error
.
index.js
const path = require('path');
const { Worker } = require('worker_threads');
const worker = new Worker(path.join(__dirname, 'worker.js'));
worker.on('message', (msg) => {
console.log('Message:');
console.log(msg);
});
worker.on('error', (err) => {
console.error('Error:');
console.error(err);
});
worker.on('exit', (code) => {
console.log('Exit code:');
console.log(code);
});
worker.js
const { parentPort } = require('worker_threads');
const VError = require('verror');
parentPort.postMessage(new Error('Native Error'));
parentPort.postMessage(new VError('VError'));
npm i verror
node index.js
Message:
Error: Native Error
at Object.<anonymous> (/home/alex/src/issues/node-worker-custom-error/worker.js:4:24)
at Module._compile (internal/modules/cjs/loader.js:1063:30)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:1092:10)
at Module.load (internal/modules/cjs/loader.js:928:32)
at Function.Module._load (internal/modules/cjs/loader.js:769:14)
at Function.executeUserEntryPoint [as runMain] (internal/modules/run_main.js:72:12)
at MessagePort.<anonymous> (internal/main/worker_thread.js:174:24)
at MessagePort.[nodejs.internal.kHybridDispatch] (internal/event_target.js:354:41)
at MessagePort.exports.emitMessage (internal/per_context/messageport.js:18:26)
Message:
{ jse_shortmsg: 'VError', jse_info: {}, message: 'VError' }
This can be very unexpected and the stack information is lost. In reality the problem I'm running into is even worse. It's not with verror but with a custom SqliteError that has it's properties as enumerable: false
. This means only an empty {}
will arrive in the other thread. So even if I've never thrown anything that is not an Error
I still end up with not-an-error inside the error
event.
Describe the solution you'd like
According to MDN the fact that Error
is serializable at all is already a blessing
Native Error types can be cloned in Chrome, and Firefox is working on it.
And I assume it's not possible to serialize custom errors in general because the class might not even exist in the other thread.
What I wish for is one of these two:
- Node.js (V8?) walks the prototype chain and sees if it finds an
Error
. I'm not suggesting doing this for arbitrary objects and MDN says "The prototype chain is not walked or duplicated.". But I think subclasses ofError
deserve that special treatment - Something along the lines of
valueOf
andtoJSON
that can be used to aid the cloning algorithm, so downgrading the Error would be in the hands of library authors
Describe alternatives you've considered
I've tried downgrading the errors in uncaughtException
event and throwing the native Error
, but you cannot have an uncaught exception inside uncaughtException
and have the thread crash with the new error instead.
And this solutions doesn't help others debugging the same issue and only seeing {}
on their error logs.