Back to Blog
Lesson 41 of the JavaScript: From Zero to Interactive Web Pages course
JavaScriptAugust 28, 20264 min read

Error Handling for Requests: Building Robust JavaScript Apps

Learn to master error handling in JavaScript. Discover how to use try/catch blocks and response validation to keep your app running when network requests fail.

javascriptfetcherror-handlingweb-developmentprogramming-basics
Close-up of colorful JavaScript code displayed on a computer monitor, ideal for tech-themed projects.

Previously in this course, we covered Building the Weather Service and Displaying Weather Data. In those lessons, we assumed the network would always cooperate. However, in production, APIs go down, users lose connectivity, and servers return unexpected data. This lesson adds error handling to your toolbelt, ensuring your app remains stable even when things go wrong.

Why Error Handling Matters

When you use fetch(), the promise only rejects if there is a network error (like being offline). It does not reject if the server returns a 404 (Not Found) or 500 (Server Error). Your code will happily process an error page as if it were valid data, leading to silent bugs. To build professional, failure-resistant code, you must adopt defensive programming by proactively validating your environment.

The try/catch Pattern

The try/catch statement allows you to "try" a block of code and "catch" any errors that occur within it. This prevents the browser from throwing a hard error in the console that halts your entire application logic.

While fetch uses promises, wrapping your logic in try/catch is the modern standard for writing readable, reliable code.

Worked Example: Fetching with Validation

Here is how you should structure a request to ensure both network stability and valid HTTP responses:

JAVASCRIPT
async function fetchWeather(city) {
  const url = CE9178">`https://api.example.com/weather?q=${city}`;

  try {
    const response = await fetch(url);

    // 1. Validate the response status
    if (!response.ok) {
      throw new Error(CE9178">`HTTP error! status: ${response.status}`);
    }

    // 2. Parse the data
    const data = await response.json();
    return data;

  } catch (error) {
    // 3. Handle errors gracefully
    console.error("Could not fetch weather:", error);
    showUserError("Unable to load weather. Please try again later.");
  }
}

function showUserError(message) {
  const errorContainer = document.getElementById(CE9178">'error-display');
  errorContainer.innerText = message;
  errorContainer.style.display = CE9178">'block';
}

Key Principles of Robustness

  1. Check response.ok: The fetch API provides the .ok property, which is true if the status code is between 200–299. Always check this before parsing JSON.
  2. User-Friendly Feedback: Never leave the user guessing. If a request fails, update the UI to inform them (e.g., using a toast notification or an error label).
  3. Fail Silently in Logs, Loudly in UI: Log the technical details to console.error for your own debugging, but show a simplified, helpful message to the user.

Hands-on Exercise

Update your weather dashboard project to include a basic error-handling wrapper.

  1. Create a div in your HTML with an ID of error-display and set its CSS display to none.
  2. Wrap your existing fetch call from our previous work inside a try/catch block.
  3. If the fetch fails or response.ok is false, change the error-display element's innerText to "Something went wrong!" and set its display to block.

Common Pitfalls

  • Assuming fetch fails on 404s: As noted, fetch treats a 404 as a successful request because the network connection worked. You must check response.ok.
  • Forgetting to parse JSON in try: If the server returns an error page in HTML format, calling .json() on that response will throw a parsing error. Always validate the status before attempting to parse.
  • Swallowing errors: Don't leave your catch block empty. If you catch an error but don't log it or notify the user, you'll have no idea why your app is "broken."

FAQ

Q: Why use try/catch if I have .catch() on my promise? A: try/catch is generally easier to read, especially when you have multiple asynchronous steps that depend on each other. It keeps your code flat rather than deeply nested.

Q: Can I catch errors in other parts of my code? A: Yes! try/catch works for any synchronous code as well, not just network requests. It's a great way to prevent one bad function from crashing your entire dashboard.

Recap

Building robust web applications requires anticipating failure. By validating response.ok, using try/catch blocks, and providing clear user feedback, you ensure that your to-do and weather dashboard remains a reliable tool for your users, even when the network is not. Consistent error handling best practices are the hallmark of a professional frontend engineer.

Up next

In the next lesson, we will look at how to formalize this pattern using async and await to make your asynchronous code look and behave more like synchronous, easy-to-read code.

Similar Posts