Don't use a simple JSON.stringify
If you want to serialize an Error in Javascript you might be tempted to simply use JSON.stringify
, but that won't be very helpful.
const error = new Error("Something went wrong");
const serialized = JSON.stringify(error);
// serialized -> '{}'
Normalize the error
Instead what I like to do is "normalize" the error (in case it's not actually an Error
object) and then use the error message:
/**
* @param {unknown} error
* @returns {Error}
*/
export function normalizeError(error) {
if (typeof error === "object" && error instanceof Error) {
return error;
} else if (typeof error === "string") {
return new Error(error);
}
// else turn this unknown thing into a string
return new Error(JSON.stringify(error));
}
// NOW I CAN CATCH ERRORS...
try {
throw new Error("Something went wrong");
} catch (error) {
const normalized = normalizeError(error);
const serialized = normalized.message;
// serialized -> "Something went wrong"
}
// AND ANYTHING ELSE
try {
throw "Who throws a string? ME!";
} catch (error) {
const normalized = normalizeError(error);
const serialized = normalized.message;
// serialized -> "Who throws a string? ME!"
}
Alternative: Use overloaded JSON.stringify
If you know you are dealing with an Error
object (so you don't need to normalize it) then you can use JSON.stringify
with a second argument to tell JSON stringify which properties to enumerate:
const error = new Error("Something went wrong");
const serialized = JSON.stringify(error, Object.getOwnPropertyNames(error));
// serialized -> '{"stack":"Error: Something went wrong\\n at REPL9:1:13\\n at Script.runInThisContext (node:vm:131:12)\\n at REPLServer.defaultEval (node:repl:522:29)\\n at bound (node:domain:416:15)\\n at REPLServer.runBound [as eval] (node:domain:427:12)\\n at REPLServer.onLine (node:repl:844:10)\\n at REPLServer.emit (node:events:390:22)\\n at REPLServer.EventEmitter.emit (node:domain:470:12)\\n at REPLServer.Interface._onLine (node:readline:418:10)\\n at REPLServer.Interface._line (node:readline:763:8)","message":"Something went wrong"}'
If you don't want the stack in there you can just list an array of the properties you want:
const error = new Error("Something went wrong");
const serialized = JSON.stringify(error, ["message", "name"]);
// serialized -> '{"message":"Something went wrong", "name": "Error"}'
Hopefully you found this post helpful, if you have any questions you can find me on Twitter.
Or from the RSS feed