devnotes.

try/catch and Custom Errors

JavaScript uses try/catch/finally to handle errors gracefully, and lets you define your own error types by extending the built-in Error class.

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

function setAge(age) {
  if (age < 0) throw new ValidationError("Age cannot be negative");
  return age;
}

try {
  setAge(-5);
} catch (err) {
  if (err instanceof ValidationError) {
    console.log("Invalid input:", err.message);
  } else {
    throw err; // re-throw anything unexpected
  }
} finally {
  console.log("Validation attempt finished");
}

Custom error classes let calling code distinguish between different failure types using instanceof, instead of fragile string-matching on err.message. Re-throwing errors you don't recognize (the else branch above) is important — silently swallowing unexpected errors makes bugs much harder to track down later.

finally always runs, whether the try block succeeded, threw, or even returned early — making it the right place for cleanup code like closing a connection or hiding a spinner, regardless of outcome.

try/catch and Custom Errors in JavaScript | DevNotes