{"id":1486,"date":"2025-05-30T13:26:58","date_gmt":"2025-05-30T13:26:58","guid":{"rendered":"https:\/\/www.wordpress-prod.sharpener.tech\/?p=1486"},"modified":"2025-06-02T11:01:37","modified_gmt":"2025-06-02T11:01:37","slug":"centralized-error-handling","status":"publish","type":"post","link":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/","title":{"rendered":"Centralized Error Handling"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"683\" src=\"https:\/\/www.wordpress-prod.sharpener.tech\/wp-content\/uploads\/2025\/05\/ChatGPT-Image-May-30-2025-06_51_03-PM-1024x683.jpg\" alt=\"\" class=\"wp-image-1487\" srcset=\"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM-1024x683.jpg 1024w, https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM-300x200.jpg 300w, https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM-768x512.jpg 768w, https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg 1536w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>&nbsp;My Experience with Error Handling and How Centralized Error Handling Helped Me<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"> &#8220;Hi everyone! Before we dive into today\u2019s topic, I want to take you back to a problem I encountered in my early days as a developer. Like many of you, I started building simple applications \u2014 small projects here and there. At first, I didn\u2019t think much about error handling. I was so focused on getting things to work that I didn&#8217;t realize how important it was to have a good strategy for managing errors.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">But as my project grew, I realized I had a problem. I had created multiple routes and API endpoints, each performing different tasks. There were tasks like user registration, login, data fetching, and updating user information. And every time something went wrong \u2014 a user didn\u2019t exist, data couldn\u2019t be fetched, or something failed on the backend \u2014 I had to handle those errors.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I started out handling each error directly inside the routes. It worked, but things got messy quickly. I had to check for errors in <strong>every single route<\/strong>. And as I added more features, I realized that my error-handling code was becoming repetitive, inconsistent, and difficult to maintain.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Imagine, you\u2019ve got 10 routes, and each one handles its own errors. If you need to change how you handle errors \u2014 for example, if you want to change the format of your error response \u2014 you\u2019d have to go into every single one of those routes and modify it. That\u2019s when I learned about <strong>centralized error handling<\/strong>, and it completely changed how I approached error management.&#8221;<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Part 1: Traditional Approach \u2013 Handling Errors in Every Route<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Instructor:<\/strong><strong><br><\/strong> &#8220;Let me show you what I mean by the traditional, non-centralized approach. In this method, every route manages its own errors. Let\u2019s consider an example where we have a few routes \u2014 one for handling user requests and one for handling product requests. I had to manually check for errors in each one.&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const express = require(&#8216;express&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const app = express();<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Route for handling user data<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.get(&#8216;\/user\/:id&#8217;, (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const user = null;&nbsp; \/\/ Simulating that no user was found<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;if (!user) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;res.status(404).json({<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;success: false,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: &#8216;User not found&#8217;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;} else {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;res.json(user);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Route for handling product data<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.get(&#8216;\/product\/:id&#8217;, (req, res) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const product = null;&nbsp; \/\/ No product found<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;if (!product) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;res.status(404).json({<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;success: false,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message: &#8216;Product not found&#8217;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;} else {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;res.json(product);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"> &#8220;In both routes, you can see that I\u2019m handling the error by checking if the user or product exists, and then responding with a 404 error if not. This seems fine for a small application, but here\u2019s the problem: as I added more routes to the app \u2014 for example, routes for handling order data, inventory management, or user authentication \u2014 I had to repeat this same error-checking logic over and over.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Now, what happens if I need to change the error response format? Let\u2019s say I want to include a more detailed message or change the status code. In the old approach, I would have to go into every single route and update it manually. The code starts to get bloated, repetitive, and hard to maintain.&#8221;<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Part 2: Introducing Centralized Error Handling<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"> &#8220;That\u2019s when I learned about <strong>centralized error handling<\/strong>, which allows me to handle all errors in a single place. Instead of repeating the same error checks in every route, I can delegate error handling to a <strong>central error handler<\/strong>. Let me show you how I refactored my code using this approach.&#8221;<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Create a Custom Error Class (ApiError)<\/strong><strong><br><\/strong><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;First, I created a custom error class called ApiError. This helps standardize errors across my app.&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">class ApiError extends Error {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;constructor(message, statusCode) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;super(message);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;this.statusCode = statusCode;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;this.name = &#8216;ApiError&#8217;;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.exports = ApiError;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"> &#8220;This ApiError class is just an extension of the basic JavaScript Error class. It includes a statusCode property that we\u2019ll use to define the HTTP status code for the error, making it easier to manage errors consistently throughout the app.&#8221;<\/p>\n\n\n\n<ol start=\"2\" class=\"wp-block-list\">\n<li><strong>Use the Custom Error in Routes<\/strong><strong><br><\/strong><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;Next, instead of manually checking for errors inside each route, I throw the custom error wherever necessary and pass it to the central error handler.&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const ApiError = require(&#8216;.\/ApiError&#8217;); \/\/ Import ApiError<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Route for handling user data<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.get(&#8216;\/user\/:id&#8217;, (req, res, next) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const user = null;&nbsp; \/\/ Simulating that no user was found<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;if (!user) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;return next(new ApiError(&#8216;User not found&#8217;, 404));&nbsp; \/\/ Pass the error to next()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.json(user);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Route for handling product data<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.get(&#8216;\/product\/:id&#8217;, (req, res, next) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const product = null;&nbsp; \/\/ No product found<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;if (!product) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;return next(new ApiError(&#8216;Product not found&#8217;, 404));&nbsp; \/\/ Pass the error to next()<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.json(product);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"> &#8220;In these routes, instead of handling the error directly, I just throw an ApiError and pass it to the next() function. This tells Express to pass the error to the next middleware, which will be our central error handler.&#8221;<\/p>\n\n\n\n<ol start=\"3\" class=\"wp-block-list\">\n<li><strong>Create the Centralized Error Handler<\/strong><strong><br><\/strong><\/li>\n<\/ol>\n\n\n\n<p class=\"wp-block-paragraph\">&#8220;Now, we need to create the actual error handler, which will catch any errors thrown in the app.&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const errorHandler = (err, req, res, next) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const statusCode = err.statusCode || 500;&nbsp; \/\/ Default to 500 if no statusCode is provided<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.status(statusCode).json({<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;success: false,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;message: err.message || &#8216;Something went wrong&#8217;,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.use(errorHandler); \/\/ Register the error handler middleware<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"> &#8220;The errorHandler middleware catches any errors passed through the next() function. It checks if the error has a statusCode. If not, it defaults to 500 (Internal Server Error). It then sends a JSON response with the error message. This way, no matter where the error happens, it gets handled in one place.&#8221;<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Part 3: Advantages of Centralized Error Handling<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"> &#8220;So, why is this approach better than handling errors in every route? Here are the key advantages of centralized error handling:&#8221;<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Single Point of Error Management:<\/strong><strong><br><\/strong> &#8220;With centralized error handling, all errors are handled in one place. You don\u2019t need to repeat error-checking code in every route.&#8221;<br><\/li>\n\n\n\n<li><strong>Consistency:<\/strong><strong><br><\/strong> &#8220;By using a custom error class, we ensure that all errors follow the same format, making it easier to debug and handle errors consistently.&#8221;<br><\/li>\n\n\n\n<li><strong>Easier Maintenance:<\/strong><strong><br><\/strong> &#8220;Changes to error handling, such as changing the format of error messages or adding more details, can be made in just one place \u2014 the error handler. You don\u2019t have to touch each route individually.&#8221;<br><\/li>\n\n\n\n<li><strong>Cleaner Code:<\/strong><strong><br><\/strong> &#8220;Routes are now focused on business logic instead of error handling. This keeps the codebase clean, maintainable, and easy to understand.&#8221;<br><\/li>\n<\/ol>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\" \/>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\"> &#8220;Centralized error handling is a simple but powerful concept that makes your code more organized, easier to manage, and scalable. As your application grows, you\u2019ll realize that having a centralized approach to error handling can save you a lot of time and effort. It\u2019s something every developer should consider implementing from the start.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I encourage you all to refactor any code that handles errors in multiple places and move it to a centralized error handler. Trust me, it will make your code more maintainable in the long run.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 6: Refactoring to Centralize Error Handling<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">We will move the error handling logic to a centralized middleware, so that each controller only deals with business logic (e.g., fetching users\/products), and the error-handling is delegated to the middleware.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>File: src\/models\/ApiError.js<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s create a custom error class that we can throw in controllers.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">class ApiError extends Error {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;constructor(message, statusCode) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;super(message);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;this.statusCode = statusCode;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;this.name = &#8216;ApiError&#8217;;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">module.exports = ApiError;<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>File: src\/controllers\/userController.js<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Now, instead of directly sending the error response, we&#8217;ll throw an ApiError.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const ApiError = require(&#8216;..\/models\/ApiError&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">exports.getUser = (req, res, next) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const user = null; \/\/ Simulating that no user was found<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;if (!user) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;return next(new ApiError(&#8216;User not found&#8217;, 404)); \/\/ Pass the error to the centralized error handler<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.json(user);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>File: src\/controllers\/productController.js<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">Similarly, in productController.js, we&#8217;ll throw an error.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const ApiError = require(&#8216;..\/models\/ApiError&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">exports.getProduct = (req, res, next) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const product = null; \/\/ Simulating that no product was found<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;if (!product) {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;return next(new ApiError(&#8216;Product not found&#8217;, 404)); \/\/ Pass the error to the centralized error handler<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;}<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.json(product);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">};<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>File: src\/app.js<\/strong><\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">In app.js, we will add a <strong>centralized error-handling middleware<\/strong> at the end of the middleware chain.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const express = require(&#8216;express&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const userRoutes = require(&#8216;.\/routes\/userRoutes&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const productRoutes = require(&#8216;.\/routes\/productRoutes&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const ApiError = require(&#8216;.\/models\/ApiError&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">const app = express();<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Use the routes<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.use(userRoutes);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.use(productRoutes);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Centralized error handler middleware<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.use((err, req, res, next) =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;const statusCode = err.statusCode || 500; \/\/ Default to 500 for server errors<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;res.status(statusCode).json({<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;success: false,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&nbsp;&nbsp;message: err.message || &#8216;Something went wrong&#8217;,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">\/\/ Start the server<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">app.listen(3000, () =&gt; {<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;console.log(&#8216;Server is running on http:\/\/localhost:3000&#8217;);<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">});<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 7: Explanation<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Now, error handling is <strong>centralized<\/strong>:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>The controllers no longer handle errors directly. Instead, they pass errors to the next function using next(new ApiError(&#8230;)).<br><\/li>\n\n\n\n<li>The <strong>centralized error handler<\/strong> at the end of the middleware chain catches any error passed to next() and sends a uniform error response to the client.<br><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Step 8: Testing the Refactored Application<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Run the app:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">bash<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">node src\/app.js<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Visiting:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>http:\/\/localhost:3000\/user\/1 will now give you a response:<br><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">json<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">{<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&#8220;success&#8221;: false,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&#8220;message&#8221;: &#8220;User not found&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>http:\/\/localhost:3000\/product\/1 will give you:<br><\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">json<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">CopyEdit<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">{<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&#8220;success&#8221;: false,<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">&nbsp;&nbsp;&#8220;message&#8221;: &#8220;Product not found&#8221;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">}<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">By refactoring the code, we&#8217;ve centralized the error-handling logic into one middleware. This makes it easier to maintain and modify error-handling behavior, as any changes only need to be made in the app.js file, instead of modifying every controller.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This structure is cleaner and more scalable, especially in larger applications. The controllers now focus only on their core responsibility \u2014 handling business logic \u2014 and delegating error handling to a dedicated middleware.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp;My Experience with Error Handling and How Centralized Error Handling Helped Me &#8220;Hi everyone! Before we dive into today\u2019s topic, I want to take you back to a problem I&hellip;<\/p>\n","protected":false},"author":6,"featured_media":1487,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[24],"tags":[],"class_list":["post-1486","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tips"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.6 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Centralized Error Handling - Sharpener Tech<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Centralized Error Handling - Sharpener Tech\" \/>\n<meta property=\"og:description\" content=\"&nbsp;My Experience with Error Handling and How Centralized Error Handling Helped Me &#8220;Hi everyone! Before we dive into today\u2019s topic, I want to take you back to a problem I&hellip;\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/\" \/>\n<meta property=\"og:site_name\" content=\"Sharpener Tech\" \/>\n<meta property=\"article:published_time\" content=\"2025-05-30T13:26:58+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2025-06-02T11:01:37+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1536\" \/>\n\t<meta property=\"og:image:height\" content=\"1024\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Julian Toppo\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Julian Toppo\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"8 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/\"},\"author\":{\"name\":\"Julian Toppo\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#\\\/schema\\\/person\\\/eb9482df421e52d30f961eae8a0fd67a\"},\"headline\":\"Centralized Error Handling\",\"datePublished\":\"2025-05-30T13:26:58+00:00\",\"dateModified\":\"2025-06-02T11:01:37+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/\"},\"wordCount\":1828,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/30132331\\\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg\",\"articleSection\":[\"Tips\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/\",\"url\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/\",\"name\":\"Centralized Error Handling - Sharpener Tech\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/30132331\\\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg\",\"datePublished\":\"2025-05-30T13:26:58+00:00\",\"dateModified\":\"2025-06-02T11:01:37+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/#primaryimage\",\"url\":\"https:\\\/\\\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/30132331\\\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg\",\"contentUrl\":\"https:\\\/\\\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\\\/blog\\\/wp-content\\\/uploads\\\/2025\\\/05\\\/30132331\\\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg\",\"width\":1536,\"height\":1024},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/centralized-error-handling\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Centralized Error Handling\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/\",\"name\":\"Sharpener Tech\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#organization\",\"name\":\"Sharpener Tech\",\"url\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/wordpress-prod.sharpener.tech\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Sharpener_logo-removebg-preview.png\",\"contentUrl\":\"https:\\\/\\\/wordpress-prod.sharpener.tech\\\/wp-content\\\/uploads\\\/2026\\\/05\\\/Sharpener_logo-removebg-preview.png\",\"width\":187,\"height\":62,\"caption\":\"Sharpener Tech\"},\"image\":{\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#\\\/schema\\\/logo\\\/image\\\/\"}},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/#\\\/schema\\\/person\\\/eb9482df421e52d30f961eae8a0fd67a\",\"name\":\"Julian Toppo\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g\",\"caption\":\"Julian Toppo\"},\"url\":\"https:\\\/\\\/www.sharpener.tech\\\/blog\\\/author\\\/julian\\\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Centralized Error Handling - Sharpener Tech","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/","og_locale":"en_US","og_type":"article","og_title":"Centralized Error Handling - Sharpener Tech","og_description":"&nbsp;My Experience with Error Handling and How Centralized Error Handling Helped Me &#8220;Hi everyone! Before we dive into today\u2019s topic, I want to take you back to a problem I&hellip;","og_url":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/","og_site_name":"Sharpener Tech","article_published_time":"2025-05-30T13:26:58+00:00","article_modified_time":"2025-06-02T11:01:37+00:00","og_image":[{"width":1536,"height":1024,"url":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg","type":"image\/jpeg"}],"author":"Julian Toppo","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Julian Toppo","Est. reading time":"8 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/#article","isPartOf":{"@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/"},"author":{"name":"Julian Toppo","@id":"https:\/\/www.sharpener.tech\/blog\/#\/schema\/person\/eb9482df421e52d30f961eae8a0fd67a"},"headline":"Centralized Error Handling","datePublished":"2025-05-30T13:26:58+00:00","dateModified":"2025-06-02T11:01:37+00:00","mainEntityOfPage":{"@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/"},"wordCount":1828,"commentCount":0,"publisher":{"@id":"https:\/\/www.sharpener.tech\/blog\/#organization"},"image":{"@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/#primaryimage"},"thumbnailUrl":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg","articleSection":["Tips"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/","url":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/","name":"Centralized Error Handling - Sharpener Tech","isPartOf":{"@id":"https:\/\/www.sharpener.tech\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/#primaryimage"},"image":{"@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/#primaryimage"},"thumbnailUrl":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg","datePublished":"2025-05-30T13:26:58+00:00","dateModified":"2025-06-02T11:01:37+00:00","breadcrumb":{"@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/#primaryimage","url":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg","contentUrl":"https:\/\/sharpener-wordpress.s3.ap-south-1.amazonaws.com\/blog\/wp-content\/uploads\/2025\/05\/30132331\/ChatGPT-Image-May-30-2025-06_51_03-PM.jpg","width":1536,"height":1024},{"@type":"BreadcrumbList","@id":"https:\/\/www.sharpener.tech\/blog\/centralized-error-handling\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.sharpener.tech\/blog\/"},{"@type":"ListItem","position":2,"name":"Centralized Error Handling"}]},{"@type":"WebSite","@id":"https:\/\/www.sharpener.tech\/blog\/#website","url":"https:\/\/www.sharpener.tech\/blog\/","name":"Sharpener Tech","description":"","publisher":{"@id":"https:\/\/www.sharpener.tech\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.sharpener.tech\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.sharpener.tech\/blog\/#organization","name":"Sharpener Tech","url":"https:\/\/www.sharpener.tech\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.sharpener.tech\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/wordpress-prod.sharpener.tech\/wp-content\/uploads\/2026\/05\/Sharpener_logo-removebg-preview.png","contentUrl":"https:\/\/wordpress-prod.sharpener.tech\/wp-content\/uploads\/2026\/05\/Sharpener_logo-removebg-preview.png","width":187,"height":62,"caption":"Sharpener Tech"},"image":{"@id":"https:\/\/www.sharpener.tech\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":"https:\/\/www.sharpener.tech\/blog\/#\/schema\/person\/eb9482df421e52d30f961eae8a0fd67a","name":"Julian Toppo","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/87799fed7134aa3bb27606b4eceeb577117023517d38b0152340c9e59376052c?s=96&d=mm&r=g","caption":"Julian Toppo"},"url":"https:\/\/www.sharpener.tech\/blog\/author\/julian\/"}]}},"_links":{"self":[{"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/posts\/1486","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/comments?post=1486"}],"version-history":[{"count":2,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/posts\/1486\/revisions"}],"predecessor-version":[{"id":1524,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/posts\/1486\/revisions\/1524"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/media\/1487"}],"wp:attachment":[{"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/media?parent=1486"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/categories?post=1486"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.sharpener.tech\/blog\/wp-json\/wp\/v2\/tags?post=1486"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}