How to Create a Custom Error in JavaScript

How do I create a custom Error in JavaScript?

Update your code to assign your prototype to the Error.prototype and the instanceof and your asserts work.

function NotImplementedError(message = "") {
this.name = "NotImplementedError";
this.message = message;
}
NotImplementedError.prototype = Error.prototype;

However, I would just throw your own object and just check the name property.

throw {name : "NotImplementedError", message : "too lazy to implement"}; 

Edit based on comments

After looking at the comments and trying to remember why I would assign prototype to Error.prototype instead of new Error() like Nicholas Zakas did in his article, I created a jsFiddle with the code below:

function NotImplementedError(message = "") {
this.name = "NotImplementedError";
this.message = message;
}
NotImplementedError.prototype = Error.prototype;

function NotImplementedError2(message = "") {
this.message = message;
}
NotImplementedError2.prototype = new Error();

try {
var e = new NotImplementedError("NotImplementedError message");
throw e;
} catch (ex1) {
console.log(ex1.stack);
console.log("ex1 instanceof NotImplementedError = " + (ex1 instanceof NotImplementedError));
console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
console.log("ex1.name = " + ex1.name);
console.log("ex1.message = " + ex1.message);
}

try {
var e = new NotImplementedError2("NotImplementedError2 message");
throw e;
} catch (ex1) {
console.log(ex1.stack);
console.log("ex1 instanceof NotImplementedError2 = " + (ex1 instanceof NotImplementedError2));
console.log("ex1 instanceof Error = " + (ex1 instanceof Error));
console.log("ex1.name = " + ex1.name);
console.log("ex1.message = " + ex1.message);
}

Correct way to create custom errors in javascript

Usually I just use throw new Error(...), but for custom errors I find the following code works pretty well and still gives you stack traces on V8, i.e. in Chrome and node.js (which you don't get just by calling Error.apply() as suggested in the other answer):

function CustomError(message) {
// Creates the this.stack getter
if (Error.captureStackTrace) Error.captureStackTrace(this, this.constructor)
this.message = message;
}
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.constructor = CustomError;
CustomError.prototype.name = 'CustomError';

For more info, see these links:

What's a good way to extend Error in JavaScript?

https://plus.google.com/+MalteUbl/posts/HPA9uYimrQg

When and why is it good to create custom exceptions?

The Object.assign approach is less robust and more of a hack, it is better to create custom error class. There is already an in-depth discussion on SO.

As you want to use additional fields, at most, introduce 2-3 custom classes for internal errors, but even that is often overkill:

  • one for NetworkError with location, path and status
  • one for UiError with component and problematic data state and maybe a message code for i18n
  • and one generic RuntimeError, or similar, for unknown cases

It makes little sense to have an error class per each potential occurrence. Unlike Java, there are no checked exceptions in JavaScript, and the goal is to have just enough data to troubleshoot the problem, without over engineering it. If you can meaningfully capture and then display in a dialog more data than message string would hold, go for it.

When designing custom errors, start with where and how you will process and show this information. Then see if you can easily collect this data where you throw it. If you do not have global error dialog or centralized error reporting, maybe just the default Error is enough, and you can place all the data into the message.

There is one special case, when you want to use errors as means of controlling the logic. Try to avoid it as much as possible, JavaScript is very flexible to not use throw as a way to let upper layer choose a different execution path. However, it is sometimes used to re-try network requests, and then it should have enough data for that.

Built-in Error object already has following fields:

  • name
  • message
  • stack

In each error, stack and message are two crucial pieces of information helping to fix the problem. Therefore it is important, when you re-throw it, to use something like this (for everything non-IE):

catch (err) {
throw new Error('New error message with added info', { cause: err });
}

Last, it helps to check what others are doing:

  • GraphQL's GraphQLError
  • Error handling hooks in VueJS (it has no custom errors)

And, JavaScript has not just Error, but also:

  • EvalError
  • RangeError
  • ReferenceError
  • SyntaxError
  • TypeError
  • URIError
  • AggregateError

You can also throw them when appropriate.

Note, that most UI frameworks handling views do not have custom error classes, nor do they need one.

How to Throw custom Errors?

You are passing the error object to the json method of the response object. But this only takes JSON parseable string as a parameter. What you can do is use -

res.json(JSON.stringify(err))

and at the place where you are using this response, you need to parse this string as JSON and then convert it into an Error object. You can use the following syntax assuming your front-end also uses javascript

err = new Error(JSON.parse(response.data))

Custom throw new Error message in JavaScript

How should I extend Error class to print "My message" or other text before the standard error output?

You might be able to do this by overwriting the stack property:

class MyError extends Error {
name = this.constructor.name;
stack = 'My custom error context data!\n' + this.stack;
}

However, I would not recommend to do this: .stack isn't really standard (yet), may or may not be used by what is actually displaying the error, and you shouldn't mess with the builtin lazy magic getter.

If this is not possible, how to completely replace standard error message? Where it even comes from?

It comes from the nodejs error propagation, which just logs uncaught exceptions before terminating the process. You can override this default behaviour by adding an uncaughtException event handler on process.

However, in the case of a CLI application, you simple shouldn't leave the exception unhandled. Catch it with try/catch around your main function, then do whatever custom error reporting you'd like to do, and call process.exit.

Javascript - Create custom errors and make sure that constructor params are valid

There's a way but ultimately I think it's bad design.

If you already know the set of valid values why not simply expose factory functions for every error types?

e.g.

// Assume encapsulated in a module

class AuthError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}

// This would get exported (factory methods for errors)
const authErrors = Object.freeze({
emailAlreadyExists(message = 'Hello world!') {
return new AuthError('auth/email-already-exists', message);
}

// other error types
});

// Client usage
throw authErrors.emailAlreadyExists('email already registered');


Related Topics



Leave a reply



Submit