Error in JavaScript: the object that describes what failed

An Error object carries a name, a message and a call stack: the native types, how to throw it, catch it and define one of your own.
3 min read
Believemy logo

A program that fails silently costs more than a program that stops. But the failure still has to carry enough to understand it: what broke, where, and why.

That is the job of the Error object, the only object in the language that captures the exact spot where it was created.


Definition

An Error is an object describing a failure. It carries three properties: name, the kind of error, message, the readable description, and stack, the run of calls that led there.

JAVASCRIPT
function divide(a, b) {
  if (b === 0) throw new Error("Division by zero");
  return a / b;
}

try {
  divide(10, 0);
} catch (err) {
  console.log(err.name, "|", err.message);   // Error | Division by zero
} finally {
  console.log("always runs");
}

throw stops the function there and then and travels up level by level to the first try it meets. With no catch anywhere, execution halts and the message goes to the console.


The native types

The language throws typed errors of its own. Recognizing the name saves a great deal of time.

TypeWhen it shows up
TypeErrorA value is not shaped as expected
ReferenceErrorA name in use exists nowhere
SyntaxErrorThe code or the JSON is malformed
RangeErrorA value falls outside the allowed bounds

All of them inherit from Error, so err instanceof Error is true for each. Testing instanceof against the precise type is what lets one case be handled on its own.


Defining your own error type

A class that extends Error is enough to create a recognizable type, to which you add whatever fields the handling needs.

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

try {
  throw new PaymentError("Card declined", "card_declined");
} catch (err) {
  if (err instanceof PaymentError) console.log(err.code);   // card_declined
}
Good to know

The second argument of new Error keeps the original failure: new Error("Unreadable configuration", { cause: lowLevelError }). The cause field removes the choice between a meaningful message and the technical trace, since both now travel together.


Frequently asked questions

Question

Can something other than an Error be thrown?

The language allows it, a string or an object go through perfectly well. It is still to be avoided: the thrown value will have no name and no stack, and the code catching it will not know where it came from. A thrown string loses most of the diagnosis.

Question

What exactly does stack hold?

The run of calls that led to the object being created, as text. Its format is not standardized and varies between engines: use it for logs and debugging, never as data to be parsed.

Question

How do you separate an expected failure from a real defect?

By defining a type for the first one. An empty cart or a declined card belong to the normal path and get recovered from, while a TypeError signals a defect to fix. That split shapes failure handling on the server, a subject covered in the Node.js course.

Related terms

Discover our javaScript glossary

Every word of JavaScript explained simply: keywords, built-in objects, methods, errors and concepts. Clear definitions and examples that actually run, to learn and to troubleshoot.

Share this article

Want to help us? Share this article on your networks or even better: on your site, in an article or in your newsletter.