Throwing Custom Errors & Error Classes
Custom errors give meaningful, specific error messages for your application. Create custom error classes for different failure types — validation errors, API errors, authentication errors.
Custom Errors
- throw new Error('message') — Throw a generic error with custom message
- Custom class — class ValidationError extends Error { }. Add properties like field, code
- instanceof — catch (e) { if (e instanceof ValidationError) ... }. Handle different errors differently
- Error codes — Add numeric codes for programmatic handling: error.code = 'AUTH_FAILED'
- Best practice — Don't throw strings: throw 'error'. Always throw Error objects for stack traces
Custom Errors Code
// Custom error classes
class ValidationError extends Error {
constructor(field, message) {
super(message);
this.name = "ValidationError";
this.field = field;
}
}
class ApiError extends Error {
constructor(status, message) {
super(message);
this.name = "ApiError";
this.status = status;
}
}
class AuthError extends Error {
constructor(message = "Authentication required") {
super(message);
this.name = "AuthError";
}
}
// Using custom errors
function validateUser(data) {
if (!data.name || data.name.length < 2) {
throw new ValidationError("name", "Name must be at least 2 characters");
}
if (!data.email || !data.email.includes("@")) {
throw new ValidationError("email", "Invalid email format");
}
if (data.age < 0 || data.age > 150) {
throw new ValidationError("age", "Age must be 0-150");
}
return true;
}
// Handle different error types
try {
validateUser({ name: "A", email: "invalid", age: 200 });
} catch (error) {
if (error instanceof ValidationError) {
console.log(`Validation failed on '${error.field}': ${error.message}`);
} else if (error instanceof ApiError) {
console.log(`API error ${error.status}: ${error.message}`);
} else {
throw error; // unexpected error — re-throw
}
}Tip
Tip
Custom errors make your API explicit. throw new ValidationError('Email is required', 'email') tells the caller exactly what failed and where. Generic Error('something went wrong') is useless for debugging.
Never swallow errors silently. Log, report, recover gracefully.
Common Mistake
Warning
Not extending Error properly. Custom errors must call super(message) in the constructor and set this.name = this.constructor.name. Without this, stack traces and instanceof checks won't work correctly.
Practice Task
Note
Custom errors: (1) Create ValidationError, NotFoundError, and AuthenticationError classes. (2) Throw them from appropriate functions. (3) Catch them separately with instanceof checks.
Quick Quiz
Key Takeaways
- Custom errors give meaningful, specific error messages for your application.
- throw new Error('message') — Throw a generic error with custom message
- Custom class — class ValidationError extends Error { }. Add properties like field, code
- instanceof — catch (e) { if (e instanceof ValidationError) ... }. Handle different errors differently