Skip to main content

Why error handling matters

Network requests fail. Servers go down. Users lose internet. APIs return unexpected data. If you don’t handle errors, your app shows a blank screen or crashes silently.

try/catch/finally

The core pattern for handling errors in async code:
Same structure, same behavior. Python catches specific exception types; JavaScript catches everything in one catch block.

Two types of fetch errors

This is where people get confused. fetch can fail in two different ways:

1. Network errors — fetch itself throws

2. HTTP errors — fetch succeeds but status is bad

fetch only throws on network failures. A 404 or 500 response is not an error from fetch’s perspective — it successfully received a response. Always check response.ok.

Handling both types

User-friendly error messages

Don’t show raw error messages to users. Translate them into something helpful:

In React

Re-throwing errors

Sometimes you want to handle an error and let the caller handle it too:
Re-throw errors when lower-level code shouldn’t decide what the user sees. Log the error for debugging, then throw it up to the component that can show a user-friendly message.

Common mistakes

An empty catch block is almost always a bug. If you catch an error, either handle it (show a message, return a fallback) or re-throw it. Silent failures are the hardest bugs to find.
When using async/await, stick with try/catch. Don’t mix in .catch() — it adds confusion without any benefit.

What’s next?

Error handling keeps your app stable. Now let’s make it feel fast with loading states — showing users what’s happening while requests are in flight.

Loading states

Show users what’s happening during requests