JavaScript Cheatsheet
Error Handling
Use this JavaScript reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.
try / catch / finally
try { riskyOperation(); JSON.parse(badJson); } catch (err) { console.error(err.message); } finally { // Runs whether or not an error occurred cleanup(); } // catch and finally are both optional, but one must be present try { op(); } finally { cleanup(); } // re-throw after cleanup try { op(); } catch { /* ES2019 — optional binding */ }
finally behavior
function example() { try { return "try"; } finally { return "finally"; // overrides try's return value } } example(); // "finally" // finally runs even if catch rethrows function safe() { try { throw new Error("oops"); } catch (err) { throw err; // re-throw } finally { console.log("this always runs"); // runs before re-throw propagates } }
Error Types
// Base class new Error("message") // Built-in subtypes new TypeError("Expected a string") // wrong type new RangeError("Must be between 0-100") // out of valid range new ReferenceError("x is not defined") // undefined variable new SyntaxError("Unexpected token") // parse error new URIError("Bad URI") // encodeURI etc. new EvalError("...") // eval issues (rare) // AggregateError (ES2021) — multiple errors new AggregateError([err1, err2], "Multiple failures") // .errors property contains the array // Error properties const err = new Error("Something failed"); err.message // "Something failed" err.name // "Error" (or "TypeError" etc.) err.stack // stack trace string (non-standard but universal) err.cause // ES2022 — original error (if provided) // ES2022: error cause new Error("Fetch failed", { cause: originalError });
Custom Error Classes
class AppError extends Error { constructor(message, code, statusCode = 500) { super(message); this.name = "AppError"; this.code = code; this.statusCode = statusCode; // Maintain proper stack trace (V8) if (Error.captureStackTrace) { Error.captureStackTrace(this, AppError); } } } class ValidationError extends AppError { constructor(field, message) { super(message, "VALIDATION_ERROR", 400); this.name = "ValidationError"; this.field = field; } } class NotFoundError extends AppError { constructor(resource) { super(`${resource} not found`, "NOT_FOUND", 404); this.name = "NotFoundError"; this.resource = resource; } } // Usage try { throw new ValidationError("email", "Invalid email format"); } catch (err) { if (err instanceof ValidationError) { console.log(err.field, err.message); // "email" "Invalid email format" } else if (err instanceof AppError) { console.log(err.statusCode, err.code); } else { throw err; // rethrow unknown errors } }
Type-Based Error Handling
try { riskyOp(); } catch (err) { if (err instanceof TypeError) { console.error("Type error:", err.message); } else if (err instanceof RangeError) { console.error("Range error:", err.message); } else if (err?.name === "AbortError") { console.log("Request was aborted"); } else { throw err; // always rethrow unrecognized errors } }
Async Error Handling
async/await
async function fetchData(url) { try { const res = await fetch(url); if (!res.ok) throw new Error(`HTTP ${res.status}: ${res.statusText}`); return await res.json(); } catch (err) { if (err instanceof SyntaxError) throw new Error("Invalid JSON response"); throw err; // propagate other errors } } // Caller try { const data = await fetchData("/api/items"); } catch (err) { console.error("Failed:", err.message); } // Inline catch for optional failure const data = await fetchData("/api/items").catch(() => null);
Promise chains
fetch("/api/users") .then(res => { if (!res.ok) throw new Error(`HTTP error ${res.status}`); return res.json(); }) .then(users => process(users)) .catch(err => { // Catches errors from ALL preceding .then() console.error("Pipeline failed:", err); }) .finally(() => setLoading(false)); // Handle errors per-step fetch(url) .then(res => res.json().catch(() => ({}))) // fallback on bad JSON .catch(err => { console.error("Fetch failed:", err); return null; // recover — chain continues with null }) .then(data => { if (data) process(data); });
Unhandled Rejections
// Browser window.addEventListener("unhandledrejection", event => { console.error("Unhandled promise rejection:", event.reason); event.preventDefault(); // suppress default browser logging }); // Node.js process.on("unhandledRejection", (reason, promise) => { console.error("Unhandled rejection:", reason); process.exit(1); }); process.on("uncaughtException", (err) => { console.error("Uncaught exception:", err); process.exit(1); });
Error Propagation Patterns
// Re-throw with context async function getUserPosts(userId) { try { const user = await fetchUser(userId); return await fetchPosts(user.id); } catch (err) { // Add context, preserve cause throw new Error(`Failed to get posts for user ${userId}`, { cause: err }); } } // Unwrap cause chain function getRootCause(err) { return err.cause ? getRootCause(err.cause) : err; } // Never swallow errors silently try { op(); } catch (err) { // BAD: empty catch — hides bugs } // At minimum, log it try { op(); } catch (err) { console.error(err); // then decide: recover, rethrow, or return fallback }
Result Pattern (functional error handling)
// Return { ok, value } / { ok: false, error } instead of throwing function safeJsonParse(str) { try { return { ok: true, value: JSON.parse(str) }; } catch (err) { return { ok: false, error: err }; } } const result = safeJsonParse('{"a":1}'); if (result.ok) { console.log(result.value); } else { console.error(result.error.message); } // Async version async function safeAsync(fn) { try { return { ok: true, value: await fn() }; } catch (error) { return { ok: false, error }; } } const { ok, value, error } = await safeAsync(() => fetchUser(id));
Assertions and Invariants
// Simple assert function assert(condition, message) { if (!condition) throw new Error(`Assertion failed: ${message}`); } assert(typeof name === "string", "name must be a string"); assert(age >= 0, "age must be non-negative"); // Type guards function requireString(val, name = "value") { if (typeof val !== "string") throw new TypeError(`${name} must be a string, got ${typeof val}`); return val; } // Exhaustive check pattern function assertNever(x) { throw new Error(`Unexpected value: ${x}`); } function handleStatus(status) { switch (status) { case "active": return doActive(); case "inactive": return doInactive(); default: assertNever(status); // TypeScript also catches this at compile time } }
Global Error Handling
// Catch all synchronous errors window.onerror = function(message, source, lineno, colno, error) { console.error(message, error); return true; // suppress default browser error }; // Or use addEventListener window.addEventListener("error", event => { console.error(event.error); }); // Resource load errors (doesn't bubble — use capture) window.addEventListener("error", event => { if (event.target !== window) { console.error("Resource failed to load:", event.target.src || event.target.href); } }, true /* capture */);