Skip to main content
Practice Problems

Error handling: try/catch/finally in JavaScript

Error Handling in JavaScript

try/catch/finally is the primary mechanism for handling runtime errors in JavaScript. It allows you to gracefully catch and recover from errors instead of crashing the application.


Basic Syntax

javascript
try { // Code that might throw an error const data = JSON.parse(invalidJson); } catch (error) { // Handle the error console.error("Parsing failed:", error.message); } finally { // Always runs, regardless of error console.log("Cleanup complete"); }

The Error Object

javascript
try { undefinedFunction(); } catch (error) { console.log(error.name); // "ReferenceError" console.log(error.message); // "undefinedFunction is not defined" console.log(error.stack); // Full stack trace }

Built-in Error Types

Error TypeWhen It Occurs
ErrorGeneric error
TypeErrorWrong type operation (null.prop)
ReferenceErrorAccessing undeclared variable
SyntaxErrorInvalid syntax (JSON.parse("{"))
RangeErrorNumber out of range (new Array(-1))
URIErrorInvalid URI function use

Throwing Custom Errors

javascript
function divide(a, b) { if (b === 0) { throw new Error("Division by zero"); } return a / b; } // Custom error class class ValidationError extends Error { constructor(field, message) { super(message); this.name = "ValidationError"; this.field = field; } } function validateAge(age) { if (typeof age !== "number") { throw new ValidationError("age", "Age must be a number"); } if (age < 0 || age > 150) { throw new ValidationError("age", "Age must be between 0 and 150"); } }

Catching Specific Errors

javascript
try { validateAge("abc"); } catch (error) { if (error instanceof ValidationError) { console.log(`Field: ${error.field}, Message: ${error.message}`); } else if (error instanceof TypeError) { console.log("Type error:", error.message); } else { throw error; // Re-throw unknown errors } }

Async Error Handling

With async/await

javascript
async function fetchUser(id) { try { const response = await fetch(`/api/users/${id}`); if (!response.ok) { throw new Error(`HTTP ${response.status}`); } return await response.json(); } catch (error) { console.error("Fetch failed:", error.message); return null; } }

With Promises

javascript
fetch("/api/data") .then(res => res.json()) .then(data => console.log(data)) .catch(error => console.error("Error:", error));

finally Block

finally always runs — even if catch has a return or throw:

javascript
function getData() { let connection; try { connection = openConnection(); return connection.query("SELECT *"); } catch (error) { return null; } finally { // Runs even after return! connection?.close(); } }

Global Error Handling

javascript
// Browser — unhandled errors window.addEventListener("error", (event) => { console.error("Global error:", event.error); }); // Unhandled promise rejections window.addEventListener("unhandledrejection", (event) => { console.error("Unhandled rejection:", event.reason); event.preventDefault(); });

Important:

Always handle errors in async code (both Promises and async/await). Create custom error classes for domain-specific errors. Use finally for cleanup (closing connections, removing loaders). Never silently swallow errors — at minimum, log them.

Short Answer

Interview ready
Premium

A concise answer to help you respond confidently on this topic during an interview.

Finished reading?
Practice Problems