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.

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:
JAVASCRIPTasync 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
- Check
response.ok: ThefetchAPI provides the.okproperty, which istrueif the status code is between 200–299. Always check this before parsing JSON. - 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).
- Fail Silently in Logs, Loudly in UI: Log the technical details to
console.errorfor 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.
- Create a
divin your HTML with an ID oferror-displayand set its CSSdisplaytonone. - Wrap your existing
fetchcall from our previous work inside atry/catchblock. - If the fetch fails or
response.okis false, change theerror-displayelement'sinnerTextto "Something went wrong!" and set itsdisplaytoblock.
Common Pitfalls
- Assuming
fetchfails on 404s: As noted,fetchtreats a 404 as a successful request because the network connection worked. You must checkresponse.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
catchblock 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.
Work with me

Next.js Full-Stack Web App Development
A fast, SEO-ready full-stack web app built with Next.js 16 — from idea to deployed product, by an engineer who ships to production.

Laravel SaaS MVP & Multi-Tenant App Development
Launch your SaaS MVP on Laravel — multi-tenant, subscription-ready, and built by the engineer behind a platform serving 10,000+ paying users.

