DEV Community

Cover image for Advanced Error Handling in Node.js
Amruta
Amruta

Posted on

Advanced Error Handling in Node.js

Error handling is an important aspect of software development that ensures your application behaves predictably and provides meaningful feedback when something goes wrong. In Node.js, effective error handling can be particularly challenging due to its asynchronous nature. This article delves into advanced techniques and best practices for managing errors in Node.js applications.

Understanding Error Types

Before diving into error handling strategies, it’s important to understand the types of errors you might encounter:

  1. Synchronous Errors:
    The errors that occur during the execution of synchronous code, can be caught using try-catch blocks.

  2. Asynchronous Errors:
    The errors occur during the execution of asynchronous code, such as callbacks, promises, and async/await functions.

  3. Operational Errors:
    Errors that represent runtime problems that the program is expected to handle (e.g., failing to connect to a database).

  4. Programmer Errors:
    Bugs in the program (e.g., type errors, assertion failures). These should generally not be caught and handled in the same way as operational errors.

Synchronous Error Handling

For synchronous code, error handling is using try-catch blocks:

try {
  // Synchronous code that might throw an error
  let result = dafaultFunction();
} catch (error) {
  console.error('An error occurred:', error.message);
  // Handle the error appropriately
}
Enter fullscreen mode Exit fullscreen mode

Asynchronous Error Handling

  • Callbacks

In callback-based asynchronous code, errors are usually the first argument in the callback function:

const fs = require('fs');
fs.readFile('/path/to/file', (err, data) => {
  if (err) {
    console.error('An error occurred:', err.message);
    // Handle the error
    return;
  }
  // Process the data
});
Enter fullscreen mode Exit fullscreen mode
  • Promises

Promises offer a cleaner way to handle asynchronous errors using .catch():

const fs = require('fs').promises;
fs.readFile('/path/to/file')
  .then(data => {
    // Process the data
  })
  .catch(err => {
    console.error('An error occurred:', err.message);
    // Handle the error
  });
Enter fullscreen mode Exit fullscreen mode
  • Async/Await

Async/await syntax allows for a more synchronous style of error handling in asynchronous code:

const fs = require('fs').promises;
async function readFile() {
  try {
    const data = await fs.readFile('/path/to/file');
    // Process the data
  } catch (err) {
    console.error('An error occurred:', err.message);
    // Handle the error
  }
}
readFile();
Enter fullscreen mode Exit fullscreen mode

Centralized Error Handling

For larger applications, centralized error handling can help manage errors more effectively. This often involves middleware in Express.js applications.

  • Express.js Middleware

Express.js provides a mechanism for handling errors via middleware. This middleware should be the last in the stack:

const express = require('express');
const app = express();

// Define routes and other middleware
app.get('/', (req, res) => {
  throw new Error('Something went wrong!');
});

// Error-handling middleware
app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).json({ message: 'Internal Server Error' });
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});
Enter fullscreen mode Exit fullscreen mode

Advanced Techniques

  • Custom Error Classes

Creating custom error classes can help distinguish between different types of errors and make error handling more granular:

class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
    Error.captureStackTrace(this, this.constructor);
  }
}

// Usage
try {
  throw new AppError('Custom error message', 400);
} catch (error) {
  if (error instanceof AppError) {
    console.error(`AppError: ${error.message} (status: ${error.statusCode})`);
  } else {
    console.error('An unexpected error occurred:', error);
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Error Logging

Implement robust error logging to monitor and diagnose issues. Tools like Winston or Bunyan can help with logging:

const winston = require('winston');
const logger = winston.createLogger({
  level: 'error',
  format: winston.format.json(),
  transports: [
    new winston.transports.File({ filename: 'error.log' })
  ]
});

// Usage
try {
  // Code that might throw an error
  throw new Error('Something went wrong');
} catch (error) {
  logger.error(error.message, { stack: error.stack });
}
Enter fullscreen mode Exit fullscreen mode
  • Global Error Handling

Handling uncaught exceptions and unhandled promise rejections ensures that no errors slip through unnoticed:

process.on('uncaughtException', (error) => {
  console.error('Uncaught Exception:', error);
  // Perform cleanup and exit process if necessary
});
process.on('unhandledRejection', (reason, promise) => {
  console.error('Unhandled Rejection at:', promise, 'reason:', reason);
  // Perform cleanup and exit process if necessary
});
Enter fullscreen mode Exit fullscreen mode

Best Practices

  • Fail Fast: Detect and handle errors as early as possible.

  • Graceful Shutdown: Ensure your application can shut down gracefully in the event of a critical error.

  • Meaningful Error Messages: Provide clear and actionable error messages.

  • Avoid Silent Failures: Always log or handle errors to avoid silent failures.

  • Test Error Scenarios: Write tests to cover potential error scenarios and ensure your error handling works as expected.

Conclusion

To effectively handle errors in Node.js, you need to use a combination of synchronous and asynchronous techniques, centralized management, and advanced strategies such as custom error classes and robust logging. By incorporating these best practices and advanced techniques, you can create robust Node.js applications that gracefully handle errors and offer an improved experience for your users.

Top comments (21)

Collapse
 
litlyx profile image
Antonio | CEO at Litlyx.com

Really good article! We have created this open-source project, where you can track anything in your web-app or website. You can customize your events too, and can be used even in production with 'Error Events' so you can always check where the exception are even in production!

The project is open-source on Github.

Antonio, CEO & Founder at Litlyx.com

Collapse
 
rkristelijn profile image
Remi Kristelijn

Great article! I want to point out that extensive logging, especially when explicitly writing to a file can result a performance issue. Therefore you could just log to the console and let e.g. kubernetes handle the logging. Also central logging is important, e.g. use of open search and e.g. npmjs.com/package/console-log-json

Collapse
 
mehedihasan2810 profile image
Mehedi Hasan

Good read

Collapse
 
the_riz profile image
Rich Winter • Edited

Good stuff.
Don't forget that Promises both resolve and reject

Collapse
 
amritak27 profile image
Amruta

You're right, Promises can resolve and reject, and it's important to handle both cases

Collapse
 
syedmuhammadaliraza profile image
Syed Muhammad Ali Raza

nice

Collapse
 
learn_with_santosh profile image
Santosh Shelar

Great advice! These best practices ensure your applications can gracefully handle errors and provide a better user experience.

Collapse
 
devpaul3000 profile image
Dev Paul

Great article. Creating custom error classes is a really powerful approach that make error handling a easy and sometimes fun

Collapse
 
mrrishimeena profile image
Rishi Kumar

Check out opensource library GitHub errsole.js , Its the first in world opensource 'logging library' which has built-in dashboard. Its much better than winston, pino and even paid cloudwatch.

Collapse
 
mrrishimeena profile image
Rishi Kumar

True, Error handling is the first part towards debugging the issues in Node.js . Its the first step towards knowing the root cause of the error. There are many more steps afterwards to find and verify the fix of the issues. But its takes hours. Thats why we build the errsole which can helps the developers to fix the errors in minutes.

Collapse
 
jackson_brown_c38e04bcf2a profile image
Info Comment hidden by post author - thread only accessible via permalink
Jackson Brown

I've been in the real estate business for over 20 years and I was always on the lookout for new lucrative investments. Bitcoin caught my eye early on, and I decided to invest $10,000 in purchasing Bitcoin. Over time, my investment shot to $600,000. This significant profit margin allowed me to expand my real estate business and purchase additional properties. However, my joy turned to panic when I received an email that seemed to be from my trading platform. It asked me to verify my account details. Without hesitation, I provided the information. Soon after, I discovered that my Bitcoin wallet had been drained. Devastated, I sought help and found a recommendation for Dumbledore web expert Recovery on a real estate forum. I contacted them immediately, hoping they could assist me. Their team was highly professional and quick in their response. They meticulously traced the fraudulent activity and managed to recover most of my funds. Dumbledore web expert also educated me on crucial security measures. They emphasized the importance of using two-factor authentication, creating strong, unique passwords, and recognizing phishing attempts. This experience was a tough lesson, but their guidance helped me secure my Bitcoin more effectively for the future. I will advise everyone to contact Dumbledore web expert if your bitcoin was stolen or you being scammed through their contact info below :

Email: dumbledorewebexpert(@)usa.com
WhatsApp: +1-(231)-425-0878

Collapse
 
jackson_brown_c38e04bcf2a profile image
Jackson Brown

I've been in the real estate business for over 20 years and I was always on the lookout for new lucrative investments. Bitcoin caught my eye early on, and I decided to invest $10,000 in purchasing Bitcoin. Over time, my investment shot to $600,000. This significant profit margin allowed me to expand my real estate business and purchase additional properties. However, my joy turned to panic when I received an email that seemed to be from my trading platform. It asked me to verify my account details. Without hesitation, I provided the information. Soon after, I discovered that my Bitcoin wallet had been drained. Devastated, I sought help and found a recommendation for Dumbledore web expert Recovery on a real estate forum. I contacted them immediately, hoping they could assist me. Their team was highly professional and quick in their response. They meticulously traced the fraudulent activity and managed to recover most of my funds. Dumbledore web expert also educated me on crucial security measures. They emphasized the importance of using two-factor authentication, creating strong, unique passwords, and recognizing phishing attempts. This experience was a tough lesson, but their guidance helped me secure my Bitcoin more effectively for the future. I will advise everyone to contact Dumbledore web expert if your bitcoin was stolen or you being scammed through their contact info below :

Email: dumbledorewebexpert(@)usa.com
WhatsApp: +1-(231)-425-0878

Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more