Handle and manage errors within the controller in Express.js to prevent the further execution of asynchronous functions

Consider a scenario where there is an API endpoint /register, designed to register new users in an application. The function utilized is asynchronous, as an attempt is made to incorporate an asynchronous process within an AuthController when performing password hashing:

authRouter.post('/register', async (req: Request, res: Response, next: NextFunction) => {
    const { username, password } = req.body;
    
    const hashedPassword = await AuthController.hashPassword(password, next);

    // execute additional tasks

Within the AuthController, error handling is demonstrated by throwing an error as shown below:

const hashPassword = async (password: string, next: NextFunction): Promise<void> => {
    try {
        throw new Error('test error');
        //return await bcrypt.hash(password, 10);
    } catch(err) {
        next(err);
    }
} 

During testing of the API, the server crashes unexpectedly, with the following log message:

[1] Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
[1]     at new NodeError (node:internal/errors:400:5)
[1]     at ServerResponse.setHeader (node:_http_outgoing:663:11)
[1]     at ServerResponse.header (C:\Users\renet\Desktop\git\rapidhcm-monorepo\api\node_modules\express\lib\response.js:794:10)
[1]     at ServerResponse.send (C:\Users\renet\Desktop\git\rapidhcm-monorepo\api\node_modules\express\lib\response.js:174:12)
[1]     at ServerResponse.json (C:\Users\renet\Desktop\git\rapidhcm-monorepo\api\node_modules\express\lib\response.js:278:15)
[1]     at ServerResponse.send (C:\Users\renet\Desktop\git\rapidhcm-monorepo\api\node_modules\express\lib\response.js:162:21)
[1]     at C:\Users\renet\Desktop\git\rapidhcm-monorepo\api\dist\src\routes\auth\auth.js:72:25
[1]     at Generator.next (<anonymous>)
[1]     at fulfilled (C:\Users\renet\Desktop\git\rapidhcm-monorepo\api\dist\src\routes\auth\auth.js:28:58)
[1]     at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
[1]   code: 'ERR_HTTP_HEADERS_SENT'
[1] }
[1]
[1] Node.js v18.13.0

The malfunction appears to be triggered by the failure of the function to halt at the catch block, but rather proceeding to the '// do something else' segment where it endeavors to send a response. Although one potential solution could involve enclosing the try {} catch{} block within the router function scope, this approach is dismissed due to two primary reasons:

  1. From a design perspective, consolidating try {} catch{} blocks into separate functions enhances code readability.
  2. A single encompassing try {} catch{} block for the entire function would be required since variables cannot be accessed outside try{} catch{} scopes.

EDIT: To provide clarity, here is the '// do something else'' code block snippet:

    try {
        await User.create({ username, password: hashedPassword ?? 's' });
        res.send({ username, password, hashedPassword });
    } catch (error) {
        console.error('Something went wrong when adding a new user', error);
        res.status(400).send({
            message: 'User already exists in the database',
        });
    }

Answer №1

Having trouble with this particular issue? It seems like my struggle came down to a misunderstanding of async/await in Javascript. The root of the problem lies in the fact that when I call

await AuthController.hashPassword(password, next)
, a promise should be returned. However, within the hashPassword function, I am actually throwing an error immediately, which is then caught in my catch(err){} block, ultimately triggering the next middleware. Unfortunately, this does not halt the execution of the 'parent' function as expected initially. The error is only caught within the hashPassword function, allowing the parent function to continue normally. While searching online, I found a question that closely resembles mine:

How do I stop execution in Express.js after catching an error from an Await call?

The main difference, it appears, is that I am attempting to handle the error within the 'child' function using try{} catch(err){} blocks

MY SOLUTION: After pondering on it, I believe structuring the code by creating a wrapper function that encapsulates all asynchronous functions and including a .catch(err) handler at the end of the wrapper may be the best approach in this scenario.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Having difficulty with utilizing array.every() properly, leading to inaccurate results

Struggling to validate an array of IDs using a custom validator in a nestjs project. The issue arises when passing the array of IDs to a service class for database querying, as the validation always returns true even with incorrect IDs. Snippet of the cus ...

Javascript's callback mechanism allows functions to be passed as arguments

I am currently delving into the intricacies of the callback mechanism in javascript, particularly typescript. If I have a function that expects a callback as an input argument, do I need to explicitly use a return statement to connect it with the actual ca ...

Instructions on utilizing type interfaces for prop drilling in my React Typescript counter

I am currently developing a basic counter app to monitor my progress in a digital card game that I enjoy playing. While attempting to pass props from the parent component to the child component, I encountered an issue where the props were not being success ...

Unable to retrieve current user data from API using axios

I'm encountering an issue with retrieving my authenticated User. Whenever I access the route where the current user is, I receive no data in my Vue file. Backend: var app = express(); app.use(cors({ methods:['GET','POST'], cr ...

The onChange function in CustomSelect is triggering an endless loop of renders in a React application using TypeScript and Material-

Currently, I am working with a mui element called CustomSelect. It functions perfectly on desktop, however, the handleChange function from onChange only console logs once. On mobile (even in development mode), it renders 51 times before crashing and displa ...

What could be causing the error message "Error: Cannot modify headers after they are sent" to appear?

I am attempting to insert data into an MS SQL server when a JSON Data API POST request is made. var express = require('express'); var app = express(); var sql = require('mssql'); // Connection string parameters. var sqlConfig = { u ...

Implementing Dynamic Component Rendering in React Native with Typescript

For the past 3 hours, I've been grappling with this particular issue: const steps = [ { Component: ChooseGameMode, props: { initialValue: gameMode, onComplete: handleChooseGameModeComplete } }, { Com ...

The outcome of using Jest with seedrandom becomes uncertain if the source code undergoes changes, leading to test failures

Here is a small reproducible test case that I've put together: https://github.com/opyate/jest-seedrandom-testcase After experimenting with seedrandom, I noticed that it provides consistent randomness, which was validated by the test (running it multi ...

When utilizing jQuery Ajax, Express.js is limited to retrieving a maximum of six consecutive results

I've encountered an interesting issue that has me stumped. Whenever I click on the "Done" button more than six times in a row, Express.js stops displaying results after the sixth one, limiting me to only seeing six results in my console. Even if I ref ...

How can NodeJS implement ThreadLocal variable functionality without relying on req and res.locals?

In a specific situation, I am required to handle business logic and logging for each request separately. This means that the data stored should not overlap with data from other requests. Using res.locals or req objects is not an option in this case becaus ...

What steps should I follow to ensure that TypeScript is aware of the specific proptypes I am implementing?

Is there a way to instruct TypeScript on the prop types that a component is receiving? For example, if multiple is set to true, I would like TypeScript to expect that selectValue will be an array of strings. If it's not present, then TypeScript should ...

The Angular SSR feature is throwing errors due to non-ESM modules present in my Express API implementation

In my Angular SSR project, I have set up my Express API to run as part of the SSR service. The app code is located in /src/app, while the API code resides in /src/api. There are some imports of the API code into the app code, primarily for using the same t ...

Switching to Next.js

In my Next JS application, I have a div that dynamically displays the currency and price of a product when a user visits a product page. <div className="flex"> <Image src={EuroCurrency} alt="Euro Sign} /> <h1 className=" ...

Encountering an issue upon pressing the 'calculate' button

Currently, I am delving into express node.js and attempting to execute a straightforward calculator code. However, whenever I click on the button, I do not receive any response, and there are no errors in my code either. I find myself a bit lost in figurin ...

Parent route being called by express route once more

One of my express routes in router/blog.js looks like this: in router/blog.js router.get('/', middleware.isLoggedIn, function(req,res){ //some code res.render('blogs'); }) After that, I have another route for adding new blogs: route ...

I need to figure out what I'm overlooking. My goal is to save my session data to a MySQL

I have successfully set up my database connection and it is running smoothly. Now, I am trying to store my session data in the database. However, when I run my server on the browser, I encounter this error message: RequestError: No connection is specified ...

Blank webpage caused by ngx TranslateService

Every time I attempt to translate Angular components using ngx-translate/core by utilizing the translateService in the constructor, the page appears blank. This is my appModule : import { NgModule } from '@angular/core'; import { BrowserModule } ...

Running multiple node applications within NGINX subdirectories

My current setup involves a Digital Ocean droplet connected to a domain. NGINX is running on the server, and I am attempting to reverse proxy multiple node apps. At the moment, there is one node express app in the root directory located at / . I'm no ...

The use of async/await within an observable function

I am looking to establish an observable that can send values to my observers. The issue lies in the fact that these values are acquired through a method that returns a promise. Is it possible to use await within the observable for the promise-returning f ...

encountering an issue: Unable to modify headers once they have been sent

I am facing an issue in my express js API where I am trying to check if the database is connected or not. However, I keep getting the error Can't set headers after they are sent.. Can someone please help me understand why this error is occurring? Belo ...