~/hackweb.dev
JavaScript Error Handling
Quiz
...

JavaScript Error Handling

beginner · updated Tue Sep 08 2026Contribute

Master try/catch, custom errors, and error handling patterns.

JavaScript Error Handling

Handle errors gracefully and create robust applications.

Basic try/catch

try {
  let data = JSON.parse(jsonString);
} catch (error) {
  console.error("Parse error:", error.message);
} finally {
  cleanup(); // Always runs
}

Throwing Errors

function divide(a, b) {
  if (b === 0) throw new Error("Cannot divide by zero");
  return a / b;
}

Error Types

Common built-in errors: TypeError, ReferenceError, RangeError, SyntaxError.

try {
  let obj = null;
  obj.foo.bar;
} catch (error) {
  console.error(error.name); // "TypeError"
}

Custom Errors

Extend Error to add domain-specific context.

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

Form Validation Example

Collect all errors instead of stopping at the first one.

function validateForm(data) {
  let errors = [];
  try {
    if (!data.email) throw new ValidationError("Email required", "email");
  } catch (e) { errors.push(e); }
  try {
    if (data.password.length < 8)
      throw new ValidationError("Password too short", "password");
  } catch (e) { errors.push(e); }
  return { valid: errors.length === 0, errors };
}

API Error Handler

Use static factory methods for common error types.

class ApiError extends Error {
  constructor(status, message) {
    super(message);
    this.status = status;
  }
  static notFound(r) { return new ApiError(404, `${r} not found`); }
  static unauthorized() { return new ApiError(401, "Unauthorized"); }
}

Error Boundary Pattern

Route different error types to specific handlers.

class ErrorBoundary {
  #handlers = new Map();
  catch(Type, handler) { this.#handlers.set(Type, handler); return this; }
  handle(error) {
    let handler = this.#handlers.get(error.constructor);
    return handler ? handler(error) : (() => { throw error; })();
  }
}

let boundary = new ErrorBoundary()
  .catch(ValidationError, e => `Validation: ${e.field}`)
  .catch(ApiError, e => `API ${e.status}: ${e.message}`);

Best Practices

  • Use specific error types — Easier to handle
  • Include context — What, where, why
  • Use finally for cleanup — Always runs
  • Don’t swallow errors — Log or re-throw

Common Mistakes

  • Empty catch blocks — Silently hiding problems
  • Throwing strings — Always throw Error objects
  • Overusing try/catch — Only where needed
  • Not providing context — Errors should be helpful