How can I catch a 404?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
A 404 response means the server could not find the requested resource. You do not usually "catch" it in one universal place; you handle it where the response is generated on the server or where the failed request is consumed on the client.
Return a 404 Deliberately on the Server
On the server side, a 404 should be the final fallback after all valid routes have had a chance to match. In an Express application, the usual pattern is to define normal routes first and then add one last middleware that sends the not-found response.
The last middleware runs only if nothing else sent a response. That is the key idea. If you place it too early, every request will look missing even when a valid route exists later in the file.
The same concept applies in other frameworks. A router tries to match a path. If it fails, your framework-specific not-found handler should return a 404 page or JSON payload that makes sense for the caller.
Check for 404 on the Client
If your code is making an HTTP request, you can handle a 404 after the server responds. For example, the Fetch API does not throw automatically for a 404. You need to inspect response.status or response.ok.
This is an important distinction. A missing page is still a valid HTTP response. Network failures, DNS problems, and CORS failures are the cases that usually reject the fetch promise before you even get a status code.
Use 404 Handling for Pages and APIs
A browser navigation request and an API request often need different 404 responses. For a normal web page, a branded error page with links back to search or the home page is helpful. For an API, structured JSON is usually the better choice because the caller needs something machine-readable.
If you serve a single-page application, be careful here. Client-side routers often want the server to return the main application shell for known app URLs, while actual missing API endpoints should still return a real 404. That is why many production setups split page routes and API routes clearly.
Logging also matters. A sudden burst of 404 responses often means a broken deploy, an outdated link, or a crawler hitting stale URLs. Recording the path, referrer, and request method makes the issue much easier to diagnose later.
Common Pitfalls
The most common mistake is treating a 404 like an exception in all cases. Many libraries only throw for transport-level failures, not for HTTP status codes, so you need an explicit status check.
Another frequent issue is registering the catch-all 404 handler before the real routes. That turns the fallback into the only route that ever runs.
Single-page applications can also produce confusing results when the server and client router disagree. A page that should load the app shell may accidentally return a server-generated 404 if the rewrite rules are incomplete.
Finally, avoid returning a generic 200 response with an error message inside the body. If the resource is missing, send an actual 404. Correct status codes make browsers, clients, logs, and monitoring behave correctly.
Summary
- A 404 is handled either where the server generates the response or where the client inspects it.
- On the server, define real routes first and place the catch-all 404 handler last.
- On the client, check
response.statusbecause a 404 is often not thrown as an exception. - Web pages and APIs usually need different not-found responses.
- Correct status codes and logging make missing-resource bugs much easier to debug.

