Raise an Error
JavaScript throw
`throw` makes your code signal "something is wrong". Always throw `Error` instances — not strings or numbers.
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).
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"
} 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).
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"
} 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.
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;
}
} 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.