Custom Exceptions: Meaningful Error Categories

Distinguish invalid marks from unrelated failures

A report may fail because a mark is invalid or because storage is unavailable. The interface should help the teacher correct a mark without treating every failure as a mark mistake.

A custom exception names a failure category that leads to a useful handling decision. In JavaScript, a class extending Error can preserve ordinary error behavior while adding a meaningful identity.

  1. Choose a category

    Group failures by what the caller can do about them.

  2. Recognize the type

    Use instanceof to handle a known validation failure.

  3. Preserve unexpected failures

    Avoid relabeling unrelated errors as user mistakes.

Failure identity guides the response

  1. Validation

    The mark exceeds the allowed maximum.

    55
  2. Category

    Create an error for the specific kind of failure.

    MarkError
  3. Handling

    Ask for a corrected input.

    Enter a mark 0–50
Read these stages alongside the complete example. They explain the relationship; they do not execute code.

A category is more stable than matching message text

Messages explain individual failures. A type can let the caller choose handling without depending on the exact wording. instanceof checks whether the error belongs to the expected class chain in this local example.

Create categories only when they help recovery, reporting or diagnosis. A different class for every punctuation change in a message does not create a useful design.

Before starting, review throwing and handling errors. These examples use JavaScript; other languages can use different syntax and rules.

Handle a MarkError and retain its message

The subclass inherits Error behavior. We set name for readable diagnosis and recognize the object through instanceof.

Known validation failures print their message; the else branch rethrows unexpected errors. This avoids falsely blaming the teacher for every possible failure.

JavaScript · local teaching example

class MarkError extends Error {
  constructor(message) { super(message); this.name = 'MarkError'; }
}
try {
  throw new MarkError('Enter a mark 0–50');
} catch (error) {
  if (error instanceof MarkError) {
    console.log(error.name);
    console.log(error.message);
  } else {
    throw error;
  }
}

Expected output

MarkError
Enter a mark 0–50

Attach context useful to a local handler

An error may identify which field failed without placing an entire student record in the message. Here the field is science.

Use context deliberately. Sensitive records do not belong in public messages or indiscriminate logs.

JavaScript · local teaching example

class MarkError extends Error {
  constructor(field) {
    super('Invalid mark');
    this.field = field;
  }
}
const error = new MarkError('science');
console.log(error.field);

Expected output

science

Apply the rule to a small change

Create an AttendanceError for a negative count and display its recognized category and message.

Worked answer

The category communicates the kind of failure; the message explains the correction. Reuse the category for related invalid attendance values rather than defining one class for each number.

JavaScript · local teaching example

class AttendanceError extends Error {}
try {
  throw new AttendanceError('Count cannot be negative');
} catch (error) {
  console.log(error instanceof AttendanceError);
  console.log(error.message);
}

Expected output

true
Count cannot be negative

Recognize mistakes and limits

Error identity may need a documented code when failures cross process or serialization boundaries; instanceof on a reconstructed plain object is not a universal distributed contract.

Do not expose secrets or whole student records merely to add context. Preserve the original cause when wrapping a lower-level failure, and avoid catching a custom type if the caller has no useful handling strategy.

For the language or tool rules used here, see JavaScript errors and handling.

Check the core idea

Why recognize MarkError by category rather than an exact message string?
Choose one answer. You can try again.

Answer and explanation

The category can guide handling even if explanatory wording changes.

Yes. Identity and explanation serve different purposes.

Apply the idea to a new situation

JavaScript · code for this question

class MarkError extends Error {
  constructor(message) { super(message); this.name = 'MarkError'; }
}
try {
  throw new MarkError('Enter a mark 0–50');
} catch (error) {
  if (error instanceof MarkError) {
    console.log(error.name);
    console.log(error.message);
  } else {
    throw error;
  }
}
What should the handler do with an unexpected error in this example?
Choose one answer. You can try again.

Answer and explanation

Rethrow it rather than relabel it as a known mark error.

Yes. The handler should not falsely categorize it.

Make error identity support a real response

Use custom categories when they distinguish recovery decisions. Keep messages useful, context restrained and unexpected failures visible.

Connect this idea with diagnostic evidence and operation-specific file failures.

Reaching the recap and completing the quizzes are separate milestones.

    Next lesson: Debugging: Reproduce, Inspect and Verify →