JS Guide
HomeQuestionsTopicsCompaniesResources
BookmarksSearch

Built for developers preparing for JavaScript, React & TypeScript interviews.

ResourcesQuestionsSupport
HomeQuestionsSearchProgress
HomeTopicsjavascriptError Handling
PrevNext
javascript
beginner
7 min read

Error Handling

async
error-handling
errors
fundamentals
try-catch

JavaScript provides try/catch/finally for synchronous error handling and .catch() or try/catch with async/await for asynchronous errors, with built-in error types like TypeError, ReferenceError, and SyntaxError.

Key Points

1try/catch/finally

try wraps risky code, catch receives the error object, finally always runs for cleanup regardless of whether an error occurred

2Error Object Properties

Every error has name (type), message (description), stack (trace), and optionally cause (ES2022) for wrapping errors

3Built-in Error Types

TypeError (wrong type usage), ReferenceError (undeclared variable), SyntaxError (invalid syntax), RangeError (value out of range)

4Async Error Handling

Use .catch() for promise chains and try/catch with async/await; forgetting to await inside try/catch lets errors escape

5Custom Errors

Extend the Error class to create domain-specific errors; enables instanceof checks for targeted handling

What You'll Learn

  • Know how try/catch/finally works and when to use each block
  • Understand the built-in error types and what causes each one
  • Know how to handle errors in asynchronous code with promises and async/await

Deep Dive

Error handling in JavaScript prevents unexpected crashes by letting you catch and respond to runtime problems gracefully. The core mechanism is try...catch...finally, and modern JavaScript extends this to asynchronous code with Promises and async/await.

try/catch/finally

  • The try block wraps code that might throw. If an exception occurs, control immediately jumps to the catch block — the remaining try code is skipped.
  • The catch block receives the error object. You can inspect its name, message, and stack properties to understand what went wrong.
  • The finally block always executes regardless of whether an error was thrown. Use it for cleanup (closing connections, releasing resources), not for control flow. Avoid return statements inside finally — they override returns from try or catch.
  • try...catch only catches runtime errors. Syntax errors that prevent the script from parsing cannot be caught.

The Error Object

  • Every error has three key properties: name (the error type, e.g., "TypeError"), message (a human-readable description), and stack (a stack trace showing where the error originated).
  • ES2022 added the cause property: throw new Error('Failed', { cause: originalError }). This lets you wrap errors while preserving the original context — essential for debugging deeply nested async operations.

Built-in Error Types

  • TypeError: Using a value in an inappropriate way — calling a non-function, accessing a property of null or undefined. The most common error in JavaScript.
  • ReferenceError: Accessing a variable that hasn't been declared or is in the temporal dead zone (TDZ).
  • SyntaxError: Invalid syntax that prevents parsing. Usually caught at load time, not at runtime — try...catch cannot catch these unless they occur inside eval() or new Function().
  • RangeError: A value is outside its allowed range, such as creating an array with a negative length or exceeding the maximum call stack size.

Async Error Handling

  • With Promises, use .catch() at the end of a chain: fetch(url).then(res => res.json()).catch(err => handle(err)). A .catch() catches errors from any preceding .then() in the chain.
  • With async/await, wrap await calls in try...catch. An awaited rejected promise throws in the catch block just like a synchronous error.
  • Unhandled promise rejections can be caught globally with window.addEventListener('unhandledrejection', handler) in browsers or process.on('unhandledRejection', handler) in Node.js.
  • Common mistake: forgetting to await a promise inside try/catch — the error escapes the catch block entirely because the promise rejects asynchronously.

Custom Errors

  • Create custom error classes by extending Error: class ValidationError extends Error { constructor(message) { super(message); this.name = 'ValidationError'; } }. This enables instanceof checks for targeted error handling.
  • Use conditional catch logic: check error instanceof TypeError vs error instanceof ValidationError to handle different error types differently.

Key Interview Distinction: throw vs return throw transfers control to the nearest catch block and unwinds the call stack. return simply exits the current function. In error handling, always throw actual Error objects (not strings or plain objects) so that you get a proper stack trace and instanceof checks work correctly.

Fun Fact

JavaScript originally had no try/catch at all — it was added in ES3 (1999). Before that, the only error handling was window.onerror, which gave you a string message with no stack trace. The Error object's stack property is still non-standard to this day — every browser formats it differently, which is why libraries like stacktrace.js exist.

Practice What You Learned

How does try/catch work in JavaScript and when should you use it?
junior
error-handling
try/catch wraps code that might throw errors: the try block runs the code, catch handles any error that occurs, and the optional finally block always executes regardless of the outcome. Use it for operations that can fail at runtime like API calls, JSON parsing, and user input processing.
Previous
DOM
Next
Events
PrevNext