1. Introduction
Built-in error types like TypeError and RangeError describe generic language-level failures, but real applications often have domain-specific failures — a failed validation, an insufficient balance, an expired session. Custom errors let you extend the built-in Error class to create named, structured error types that carry extra context and can be distinguished from one another with instanceof.
Cricket analogy: A generic 'no-ball' call is like TypeError — a broad rule violation — but a specific 'front-foot no-ball due to overstepping' call is like a custom error, giving umpires a named, structured reason they can distinguish from a 'height no-ball' using replay review, the way instanceof distinguishes custom error types.
2. Syntax
class CustomError extends Error {
constructor(message) {
super(message);
this.name = "CustomError";
}
}
throw new CustomError("Custom failure message");3. Explanation
A custom error is defined with class X extends Error. Inside the constructor, super(message) MUST be called first — it invokes the Error constructor, which sets up this.message and the stack trace. After calling super, you should explicitly set this.name = "YourErrorName", because by default it inherits the generic name "Error" from the parent class, which makes err.name and stack traces less useful for identifying the specific failure.
Cricket analogy: Extending the Error class is like a specialist bowling academy extending the base fielding academy's curriculum — you must first complete the base academy's core certification (super(message)) before adding your specialty badge, and you must explicitly relabel your certificate 'Fast Bowling Specialist' instead of leaving it as the generic 'Academy Graduate' (this.name).
You can attach any extra properties you need (a field name, an HTTP status code, an original balance) directly on this inside the constructor, after calling super(). Consumers can then branch on the specific error type using instanceof, which correctly follows the prototype chain as long as the class properly extends Error.
Cricket analogy: Attaching extra properties like this.oversRemaining after calling super() is like a match report adding specific fields — overs left, required run rate — to a standard incident report; commentators can then branch their coverage using the report's specific type, just as code branches with instanceof.
Order matters: this is not usable in a derived class constructor until super() has been called, because super() is what actually creates the this binding for a subclass. Setting this.name before calling super(message) throws a ReferenceError.
4. Example
class ValidationError extends Error {
constructor(message, field) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
class InsufficientFundsError extends Error {
constructor(balance, amount) {
super(`Cannot withdraw ${amount}, balance is only ${balance}`);
this.name = "InsufficientFundsError";
this.balance = balance;
this.amount = amount;
}
}
function withdraw(balance, amount) {
if (typeof amount !== "number" || amount <= 0) {
throw new ValidationError("Amount must be a positive number", "amount");
}
if (amount > balance) {
throw new InsufficientFundsError(balance, amount);
}
return balance - amount;
}
const attempts = [
() => withdraw(100, 50),
() => withdraw(100, 200),
() => withdraw(100, -10),
];
for (const attempt of attempts) {
try {
console.log("New balance:", attempt());
} catch (err) {
if (err instanceof InsufficientFundsError) {
console.log(`${err.name}: ${err.message}`);
} else if (err instanceof ValidationError) {
console.log(`${err.name} (${err.field}): ${err.message}`);
} else {
console.log("Unknown error:", err.message);
}
}
}5. Output
New balance: 50
InsufficientFundsError: Cannot withdraw 200, balance is only 100
ValidationError (amount): Amount must be a positive number6. Key Takeaways
- Custom errors extend
Errorand must callsuper(message)before usingthis. - Always set
this.nameexplicitly soerr.nameand stack traces identify the specific error type. - Extra domain data (field, status code, balance, etc.) can be attached as regular properties on
this. - Use
instanceofto branch handling logic based on the specific error subclass. - Order multiple
instanceofchecks from most specific to least specific when a hierarchy of custom errors exists.
Practice what you learned
1. What must be the first statement inside a custom error's constructor when extending `Error`?
2. What happens if you access `this` before calling `super()` in a derived class constructor?
3. Why explicitly set `this.name` in a custom error class?
4. Which operator correctly identifies a specific custom error subclass in a catch block?
5. In the InsufficientFundsError example, what is `err.message` when balance=100 and amount=200?
Was this page helpful?
You May Also Like
Error Handling in JavaScript
How JavaScript represents runtime failures with Error objects and the built-in TypeError, RangeError, ReferenceError, and SyntaxError types.
try-catch in JavaScript
The mechanics of the try, catch, and finally blocks, including execution order and how finally interacts with return statements.
Classes in JavaScript
How ES6 class syntax provides a cleaner, structured way to create objects and implement object-oriented patterns on top of JavaScript's prototype system.
Inheritance in JavaScript
How the `extends` and `super` keywords let one class build on another, sharing and overriding behavior while respecting strict initialization order.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics