JavaScript throw

Raise an Error

JavaScript throw

`throw` makes your code signal "something is wrong". Always throw `Error` instances — not strings or numbers.

3 min read Level 2/5 #throw#errors#exceptions
What you'll learn
  • Throw an `Error` with a useful message
  • Add a `cause` for nested errors
  • Define a custom error subclass

throw raises an error. Anywhere along the call stack, a try/catch can grab it. If nothing catches, the program crashes (browsers log the error to the console; Node exits non-zero).

Throw an Error script.js
function divide(a, b) {
  if (b === 0) throw new Error("cannot divide by zero");
  return a / b;
}

try {
  divide(10, 0);
} catch (e) {
  console.log(e.message);  // "cannot divide by zero"
}
▶ Preview: console

Always Throw Error Instances

You CAN technically throw anything — strings, numbers, objects. But Error instances carry a stack trace and integrate with debuggers, loggers, and the runtime.

// Don't:
throw "something failed";

// Don't:
throw { code: "OOPS", reason: "..." };

// Do:
throw new Error("something failed");

Add a cause for Wrapped Errors

When you catch an error and throw a new one, attach the original with cause (ES2022).

Error cause script.js
async function loadUser(id) {
  try {
    return await fetchUserById(id);
  } catch (e) {
    throw new Error(`Could not load user ${id}`, { cause: e });
  }
}

async function fetchUserById() {
  throw new Error("API timeout");
}

try {
  await loadUser(42);
} catch (e) {
  console.log(e.message);         // "Could not load user 42"
  console.log(e.cause?.message);  // "API timeout"
}
▶ Preview: console

Now both the high-level message (“Could not load user”) and the specific cause (“API timeout”) travel together.

Custom Error Subclasses

For domain-specific errors, subclass Error.

Custom error class script.js
class ValidationError extends Error {
  constructor(field, message) {
    super(`${field}: ${message}`);
    this.name = "ValidationError";
    this.field = field;
  }
}

try {
  throw new ValidationError("email", "must be a valid address");
} catch (e) {
  if (e instanceof ValidationError) {
    console.log("validation failed on", e.field, "→", e.message);
  } else {
    throw e;
  }
}
▶ Preview: console

Subclassing makes instanceof checks meaningful, lets you attach extra fields, and gives the error a distinct name in stack traces.

Throw From async

Throwing inside an async function becomes a rejected Promise:

async function readConfig() {
  throw new Error("config missing");
}

readConfig().catch((e) => console.log("rejected:", e.message));

Up Next

The built-in error types — TypeError, RangeError, and friends.

JavaScript Error Types →