SKU // 110

JavaScript Error Object

Every error JavaScript throws is an Error object. It carries the information you need to understand and handle the problem: what kind of error it is, what went wrong, where it happened, and sometimes what caused it. You can create these objects yourself, too, including your own custom error types.

// What's Inside an Error

try {
  null.length;
} catch (err) {
  console.log(err.name);
  console.log(err.message);
  console.log(String(err));        // "name: message"
}
TypeError Cannot read properties of null (reading 'length') TypeError: Cannot read properties of null (reading 'length')
Property Holds
nameThe type of error, like "TypeError"
messageWhat went wrong, as text
stackWhere it happened: the chain of function calls, with line numbers
causeThe original error that led to this one (optional, 2022)

// The stack Property

stack is a string starting with the error itself, followed by one line per function call that led to it, most recent first. It is exactly what the console shows under an uncaught error:

function inner() { return null.x; }
function outer() { return inner(); }

try {
  outer();
} catch (err) {
  console.log(typeof err.stack);
  console.log(err.stack.split("\n")[0]);
}
string TypeError: Cannot read properties of null (reading 'x')

The following lines look like at inner (script.js:1:33) then at outer (script.js:2:33): the error happened in inner, which was called by outer. The exact format differs between browsers.

W3Schools error
Its list of non-standard properties marks stack as "Firefox only." Every major browser (Chrome, Edge, Firefox, Safari) supports stack; only the text format differs.

// Creating Errors

Create an error with new Error(message). Calling Error(message) without new does the same thing. Each built-in type has its own constructor, and every one of them is also an Error:

const e1 = new Error("Something failed");
const e2 = new RangeError("Too big");

console.log(e1.name, e2.name);
console.log(e2 instanceof RangeError, e2 instanceof Error);
console.log(String(e2));
Error RangeError true true RangeError: Too big

// Error Names

ErrorA general error (the parent of all the others)
ReferenceErrorA name that does not exist
TypeErrorA value used in a way its type does not allow
RangeErrorA number outside the allowed range
SyntaxErrorCode or JSON that breaks the grammar rules
URIErrorBroken URL encoding in decodeURI and similar
AggregateErrorSeveral errors wrapped together (2021)
EvalErrorLegacy: no longer thrown by modern JavaScript
Note
W3Schools says "Six different values can be returned by the error name property." There are more: AggregateError is built in, and name is an ordinary property, so custom errors (below) can have any name you like.

// cause: Keeping the Original Error

When you catch a low-level error and throw a clearer one, pass the original as cause so no information is lost:

function loadSettings(text) {
  try {
    return JSON.parse(text);
  } catch (err) {
    throw new Error("Could not load settings", { cause: err });
  }
}

try {
  loadSettings("{oops");
} catch (err) {
  console.log(err.message);
  console.log(err.cause.name);
}
Could not load settings SyntaxError

// Error.isError() (New in 2026)

Error.isError(x) returns true only for real Error objects. Unlike instanceof Error, it also works for errors that come from another window or frame, and it is not fooled by a plain object that just has the same properties:

console.log(Error.isError(new TypeError("x")));
console.log(Error.isError({ name: "Error", message: "x" }));
console.log(Error.isError("x"));
true false false

It is very new, so older browsers do not have it. err instanceof Error works everywhere for everyday code.

// Custom Error Types

You can make your own error type, so your code can tell "the user typed something wrong" apart from a real bug. It uses two pieces of class syntax this course has not covered: extends Error means "a ValidationError is a kind of Error, with everything an Error has," and super(message) runs Error's own setup so message and stack are filled in:

class ValidationError extends Error {
  constructor(message, field) {
    super(message);
    this.name = "ValidationError";
    this.field = field;
  }
}

try {
  throw new ValidationError("Email is required", "email");
} catch (err) {
  console.log(String(err));
  console.log(err.field);
  console.log(err instanceof ValidationError, err instanceof Error);
}
ValidationError: Email is required email true true

// Handling Errors by Type

With custom types, a catch block can respond to each kind of problem differently, and pass on anything unexpected (JS Error Statements):

function save(form) {
  try {
    if (!form.email) throw new ValidationError("Email is required", "email");
    return "Saved";
  } catch (err) {
    if (err instanceof ValidationError) {
      return "Please fix the " + err.field + " field";
    }
    throw err;
  }
}

class ValidationError extends Error {
  constructor(message, field) {
    super(message);
    this.name = "ValidationError";
    this.field = field;
  }
}

console.log(save({ email: "ava@school.org" }));
console.log(save({}));
Saved Please fix the email field

// Non-Standard Properties

In older code you may see properties that only one browser ever had. Do not use them; they will not work for most of your users:

Property Where it works Use instead
description, numberOld Microsoft browsers onlyUse message and name
fileName, lineNumber, columnNumberFirefox onlyRead stack instead
toSource()RemovedUse String(err)
arguments, callerDeprecated function propertiesNot needed

// Quick Check

What does this log?

const e = new RangeError("Too big");
console.log(e.name, e instanceof Error, String(e));
Show answer
RangeError true RangeError: Too big. A RangeError is a kind of Error, and converting an error to a string gives "name: message".

Which property holds the text you passed to new Error("...")?

  1. name
  2. message
  3. stack
  4. description
Show answer
B. name is the type, stack is where it happened, and description is a non-standard Microsoft property.

Why pass { cause: err } when you throw a new, clearer error?

Show answer
So the original error is not lost. The new message explains the problem in your program's terms, and cause keeps the low-level details (its name, message, and stack) for debugging.

// Try It

  1. Click Open Playground and run it. Then catch two more built-in errors and log name, message, and the first line of stack
  2. Wrap a JSON.parse failure in a new Error with a cause, then log both messages
  3. Create a ValidationError class and throw it for a missing username
  4. Write a catch that handles ValidationError and rethrows everything else
// Video Walkthroughs
Last updated: Oct 10, 2026, 1:50 AM ET