Topic 14 / 15

Error Handling & Debugging

~9 min read  //  JavaScript Series  //  Coding India

try / catch / finally

try {
  const data = JSON.parse(rawInput);     // throws on invalid JSON
  process(data);
} catch (error) {
  console.error("Invalid input:", error.message);
} finally {
  hideSpinner();                          // always runs
}

Throw Error objects (never bare strings — they lose the stack trace):

function setPrice(amount) {
  if (amount < 0) {
    throw new Error(`price cannot be negative, got ${amount}`);
  }
}

Custom Error Classes

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

try {
  await api("/courses");
} catch (err) {
  if (err instanceof ApiError && err.status === 401) {
    redirectToLogin();
  } else {
    throw err;                 // don't swallow what you can't handle
  }
}

Async Errors

With await, rejected Promises become throwable — regular try/catch works. Without it, you need .catch():

// fire-and-forget still needs a handler
saveDraft().catch(err => console.error("autosave failed", err));

Global last-resort traps (for logging services like Sentry):

window.addEventListener("error", e => report(e.error));
window.addEventListener("unhandledrejection", e => report(e.reason));

Debugging Beyond console.log

Breakpoints beat print statements. In DevTools → Sources, click a line number, reload, and execution pauses there: inspect every variable, hover over expressions, step line by line (F10 step over, F11 step into, F8 resume). Or drop a breakpoint from code:

function calculateTotal(cart) {
  debugger;          // pauses here when DevTools is open
  ...
}

Console power-ups:

console.table(users);                 // arrays of objects as a table
console.group("checkout"); ... console.groupEnd();
console.time("render"); ... console.timeEnd("render");   // quick timing
console.trace();                      // who called me?

Reading a Stack Trace

TypeError: Cannot read properties of undefined (reading 'name')
    at renderCard (app.js:42:18)
    at app.js:51:9

Top line: what happened and where. undefined (reading 'name') means you did something.name where something was undefined — work backwards from line 42 to find which variable, and why it was undefined. The Network tab (failed requests) and the “Pause on exceptions” button cover most of the rest of real-world debugging.