Frontend Master

JavaScript Curriculum

Error Handling
+60 XP

Error Handling

medium
~30 min·60 XP

The coffee shop menu fetch fails silently when the API is down. The order form throws a TypeError when querySelector returns null. A structured error handling approach means the user always gets useful feedback, never a blank page.

Error Handling

Errors happen — network failures, null references, invalid input, server outages. The question is not if your code will encounter errors, but how well it handles them when they occur.

JavaScript Error Types

Know your enemy — five error types and how to handle each:

error types — click to explore each one

TypeError

Wrong type of thing for this operation

common triggers

Calling a non-function, accessing properties on null/undefined, wrong method for the type

example code

null.name
// TypeError: Cannot read properties of null

const n = 42
n.toUpperCase()
// TypeError: n.toUpperCase is not a function

how to catch

try { ... } catch (err) {
  if (err instanceof TypeError) {
    // handle it
  }
}

💡 in practice

The most common runtime error. Usually means you assumed something was an object or function when it was actually null, undefined, or a primitive.

</errortypeexplorer2>
ℹ️instanceof for targeted error handling
In a catch block, `err` could be any kind of error. Use `err instanceof TypeError` to check the type and respond appropriately. `err.name === 'TypeError'` also works. This lets you show different messages for network failures vs HTTP errors vs validation failures.

try/catch/finally — Interactive Simulator

See how errors propagate and how each block runs:

try-catch.js

Parsing corrupted localStorage data — without try/catch the whole app crashes.

try {
  const raw  = localStorage.getItem('cart')
  const cart = JSON.parse(raw)   // raw = '{bad}'
  renderCart(cart)
} catch (err) {
  console.error('Bad cart data:', err.message)
  localStorage.removeItem('cart') // reset
  renderCart([])                  // safe fallback
}
💡finally is your cleanup guarantee
The `finally` block always runs — whether the try succeeded, threw, or the catch handled it. Use it for cleanup that must happen regardless: hiding a spinner, releasing a lock, closing a connection. Never put cleanup only in try — it won't run if an error occurs.

Fetch Error Handling — Status Codes

fetch() has two failure modes — understand both:

fetch-error-handler.js
Simulate scenario
idle
async function loadMenu() {
  try {
    const res = await fetch('/api/menu')
    //           ↑ rejects ONLY on network failure

    if (!res.ok) {
      // 404, 500 etc — must check manually
      throw new Error(`HTTP ${res.status}: ${res.statusText}`)
    }

    const data = await res.json()
    //             ↑ throws SyntaxError if body is not valid JSON

    renderCards(data.items)

  } catch (err) {
    if (err instanceof TypeError) {
      showBanner('No internet connection')
    } else if (err.message.startsWith('HTTP 4')) {
      showBanner('Content not found')
    } else if (err.message.startsWith('HTTP 5')) {
      showBanner('Server error — try again later')
    } else if (err instanceof SyntaxError) {
      showBanner('Unexpected response format')
    } else {
      showBanner('Something went wrong')
    }
  }
}
⚠️fetch only rejects on network failure
A 404 or 500 response does NOT reject the fetch Promise — it resolves with `res.ok === false`. Always check `if (!res.ok) throw new Error(...)` before calling `res.json()`. Catching a TypeError means no network. Catching your thrown Error means a bad status code.

Your Challenge

Write a fetchWithHandling(url) helper that: awaits fetch, checks res.ok (throws on bad status), parses JSON. In the catch block, uses instanceof to distinguish network errors from HTTP errors. Create a class ValidationError extends Error and throw it from your form validator. Catch it with err instanceof ValidationError.

Challenge

Wrap your loadMenu() function in a full error handler: distinguish TypeError (offline) from HTTP errors, show different UI for each. Create a custom ValidationError class that extends Error, and use instanceof to handle it differently in the catch block.

trycatchfinallythrowErrorTypeErrorReferenceErrorinstanceofcustom-errorerror.messageerror.namefetch-errorsres.ok
Error Handling | Nexus Learn