Proper error handling is crucial for building stable and user-friendly APIs. In this section, we’ll learn how to handle:
-
Invalid routes (404 errors)
-
Controller-level application errors (e.g., user not found)
-
Centralized error response handling (using middleware)
1. Handling Unknown Routes (404 Errors)
When a user hits a route that doesn’t exist (e.g., /api/user/signup
which hasn’t been defined), we should return a proper 404 Not Found
error.
Let’s add this functionality in our Server.ts
:
// server.ts (only relevant part shown) export class Server { constructor() { this.setConfigurations(); this.setRoutes(); this.error404Handler(); // Always keep this after all routes this.handleErrors(); // Global error handler (must come last) } error404Handler() { this.app.use((req, res) => { res.status(404).json({ message: ‘Not Found’, status_code: 404 }); }); } }
This ensures that any undefined routes return a structured 404 response, improving the API’s robustness.
2. Avoiding Repetitive Code in Controllers
Let’s look at this login
method in the UserController
:
// UserController.ts (inefficient approach) export class UserController { static login(req, res) { res.status(422).json({ message: ‘Username and Password do not match’, status_code: 422 }); } }
This works, but it’s not DRY. Repeating the same response structure for every error is inefficient and unmaintainable.
3. Centralized Error Handling with Middleware
Instead of returning errors directly from controllers, we throw or forward them using next()
and catch them in a global error handler:
// server.ts handleErrors() { this.app.use((error, req, res, next) => { const errorStatus = req.errorStatus || 500; res.status(errorStatus).json({ message: error.message || ‘Something went wrong. Please try again later.’, status_code: errorStatus }); }); }
Now update the controller to use next()
:
// UserController.ts export class UserController { static login(req, res, next) { const error = new Error(‘User does not exist’); (error as any).errorStatus = 422; // Optional custom status next(error); } }
This approach allows consistent formatting of all error responses via one middleware.
4. Demonstrating Control Flow
You can even demonstrate control flow based on conditions using next()
:
// UserController.ts export class UserController { static login(req, res, next) { const error = new Error(‘User does not exist’); return next(error); // Will trigger global error handler } static test(req, res) { console.log(‘Test route called’); res.send(‘OK’); } }
If you call
next(error)
, it goes to error middleware.
If you call justnext()
, it moves to the next route or middleware.
Final Project Structure (So Far)
nodejs-project/ ├── node_modules/ ├── src/ │ ├── controllers/ │ │ └── UserController.ts │ ├── environments/ │ │ ├── dev.env.ts │ │ ├── env.ts │ │ └── prod.env.ts │ ├── routes/ │ │ └── UserRouter.ts │ ├── index.ts │ ├── server.ts ├── package.json ├── package-lock.json ├── tsconfig.json
Sample Files Recap
✅ UserController.ts
[ export class UserController { static login(req, res, next) { const error = new Error(‘User does not exist’); (error as any).errorStatus = 422; next(error); } }
✅ Server.ts (Error-Related Snippets)
export class Server { // Inside constructor this.setConfigurations(); this.setRoutes(); this.error404Handler(); this.handleErrors(); handleErrors() { this.app.use((error, req, res, next) => { const errorStatus = (error as any).errorStatus || 500; res.status(errorStatus).json({ message: error.message || ‘Something went wrong. Please try again later.’, status_code: errorStatus }); }); } error404Handler() { this.app.use((req, res) => { res.status(404).json({ message: ‘Not Found’, status_code: 404 }); }); } }
✅ Testing the Error Handling
Try hitting:
-
/api/user/login
→ returnsUser does not exist
(custom 422 error) -
/api/user/signup
→ returnsNot Found
(generic 404 error)
Summary
By using centralized error handling, we:
-
Improve code readability and maintainability
-
Follow DRY (Don’t Repeat Yourself) principles
-
Deliver consistent API error responses
-
Prevent application crashes and undefined behaviors