Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

347
Views
When and why is it good to create custom exceptions?

I am working on a complex application with different types of errors, services, and domain concepts.

In order to throw "object" errors, there are two different approaches that come to my mind:

  1. Applying Object.assign() to an Error object (easy option if I just need to throw a single or a couple of errors that follows this form):

function f() {
  const err = new Error();

  Object.assign(err, {
    name: "ServiceError",
    code: "service/some-string-code",
    message: "Some message",
  });

  throw err;
}

try {
  f();
} catch(err) {
  console.log(err instanceof Error);
}

  1. Creating custom errors (extending the Error class)

class MyServiceError extends Error {
  constructor(code, message) {
    super(message);
  
    this.name = "ServiceError";
    this.code = code;
  }
}

function f() {
  const err = new MyServiceError("service/some-string-code", "Some message");

  throw err;
}

try {
  f();
} catch(err) {
  console.log(err instanceof Error);
  console.log(err instanceof MyServiceError);
}

What are the pros and cons between both "custom errors definitions".

Also, if I choose the second approach, it seems that I will need to create multiple CustomError classes for different domain concepts, services, etc. in order to achieve symmetric code, and a clean architecture... (???) Which in turn I see as reinventing the wheel and adding unnecessary code, because perhaps not all the concepts of the application should need a custom type of exception.

Are both practices considered valid in JavaScript?

Note: throwing objects or string or stuff like that seems really bad to me, as we are not able to get the stack trace, validate instances etc.

// This seems bad to me. Isn't it an anti-pattern?
throw {
   code: "",
   message: "",
   name: ""
}
about 4 years ago · Juan Pablo Isaza
1 answers
Answer question

0

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.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!