Cannot set headers after they are sent to the client in JS

avatar
Borislav Hadzhiev

Last updated: Mar 2, 2024
3 min

banner

# Cannot set headers after they are sent to the client in JS

The "Cannot set headers after they are sent to the client" error occurs when the server in an express.js application sends more than one response for a single request, e.g. calling res.json() twice.

To solve the error, make sure to only send a single response for each request.

cannot set headers after they are sent to client

Here are some examples of how the error occurs.

index.js
app.get('/a', (req, res) => { res.send('Hello World!'); // ⛔️ Calling send method twice res.send('Hello World!'); }); // -------------------------------------------------- app.get('/b', (req, res) => { res.setHeader('Content-Type', 'application/json'); res.send('Hello World!'); // ⛔️ Setting headers after the response has been sent res.setHeader('Content-Type', 'text/html'); }); // -------------------------------------------------- app.get('/c', (req, res) => { // ⛔️ Using both send and redirect in a single response res.send('Hello World!!!'); res.redirect('/articles'); });

Here is the complete error message:

shell
Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client

# Don't send two responses for a single request

The issue in the first example is that we used the res.send() method twice in a single route handler.

index.js
app.get('/a', (req, res) => { res.send('Hello World!'); // ⛔️ Calling send method twice res.send('Hello World!'); });

We sent two responses for a single HTTP request which caused the error.

This can be a lot more difficult to identify when your code has nested if statements and promises. A solution you can try is to return the response, e.g. return res.json().

# Don't use res.setHeader() after sending a response to the client

The second example tries to use the res.setHeader() method after we have already sent the response. This also causes the error.

index.js
app.get('/b', (req, res) => { res.setHeader('Content-Type', 'application/json'); res.send('Hello World!'); // ⛔️ Setting headers after the response has been sent ⛔️ res.setHeader('Content-Type', 'text/html'); });

# Don't use res.send and res.redirect in a single response

The third example uses the res.send() and res.redirect() methods and ends up sending two responses to the client.

index.js
app.get('/c', (req, res) => { // ⛔️ Using both send and redirect in a single response res.send('Hello World!!!'); res.redirect('/articles'); });

# Don't call the next() function twice in the same middleware

You might also be calling the next() function multiple times in a single middleware.

# Only call a single function that sends a response to the client

Make sure to only call a single function that sends a response for each request. These functions include:

  • res.redirect()
  • res.render()
  • res.send()
  • res.json()

Here's another common example of how the error occurs.

index.js
app.get('/a', (req, res) => { if (5 === 5) { // 👇️ this runs res.send('Hello'); } else if (10 === 50) { res.send('Bye'); } // 👇️ this also runs res.send('This also runs'); });
The code for this article is available on GitHub

We didn't return from our if and else if statements, so the last line is also run, which causes the error.

# Return the response to avoid sending multiple responses

To avoid this, simply return the response.

index.js
app.get('/a', (req, res) => { if (5 === 5) { return res.send('Hello'); } else if (10 === 50) { return res.send('Bye'); } return res.send('This also runs'); });
The code for this article is available on GitHub
Now we know that the route handler will only return a single response because we used the return statement.

If you're working with async code, use async await because it makes your code more intuitive and readable.

This helps you avoid getting race conditions due to getting confused about which part of your code runs when.

index.js
app.get('/a', async (req, res) => { const status = 200; if (status === 200) { const result = await Promise.resolve('data'); return res.send(result); } else if (status === 404) { const err = await Promise.resolve('page not found'); return res.send(err); } return res.send('Server error'); });
The code for this article is available on GitHub

When using async/await, the code reads as if it were synchronous and is much easier to follow.

This helps us to avoid returning a response before the promise has been resolved and then returning another response after.

I've also written an article on how to access the value of a Promise.

# Additional Resources

You can learn more about the related topics by checking out the following tutorials:

I wrote a book in which I share everything I know about how to become a better, more efficient programmer.
book cover
You can use the search field on my Home Page to filter through all of my articles.