Don't Catch What You Can't Handle

The golden rule of catch: handle only the errors you know about. Re-throw everything else so it can be handled higher up the chain.

class ValidationError extends Error { constructor(msg) { super(msg); this.name = 'ValidationError'; } }

try {
  const user = JSON.parse(jsonString);
  if (!user.name) throw new ValidationError('Name is required');
  
  someUndefinedFunction(); // Unexpected bug
} catch (err) {
  if (err instanceof ValidationError) {
    // We know this one — handle it gracefully
    showFormError(err.message);
  } else {
    // Unknown error — re-throw it!
    throw err; // Goes to the next outer try..catch or window.onerror
  }
}

The Anti-Pattern: Swallowing All Errors

// NEVER DO THIS:
try {
  doSomething();
} catch (err) {
  // Empty catch — error is silently swallowed!
  // Real bugs become invisible, impossible to debug
}
Important

If you " swallow " all errors with an empty catch {}, you'll never know about serious logic bugs in your application. Always re-throw errors you don't know how to handle.

Caution

A re-thrown error travels to the next outer try..catch block, or ultimately to the global window.onerror handler.