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

avatar

Borislav Hadzhiev

Tue Oct 19 20212 min read

banner

Photo by Antony

Cannot set headers after they are sent to the client #

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 response has been sent res.setHeader('Content-Type', 'text/html'); }); app.get('/c', (req, res) => { // โ›”๏ธ Using both send and redirect in a single request res.send('Hello World!!!'); res.redirect('/articles'); });

The first example is quite simple - it uses the res.send method twice in a single route handler.

Since we send two responses on a single Http request, the error occurs.

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

The second example tries to use the setHeader method after we have already sent the response, which also causes the error.

The third example uses the send and redirect methods sending two responses to the client.

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

Make sure to only call a single function that ends 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'); } res.send('This also runs'); });

Because we didn't return from our if and else if statements, the last line is also ran, which causes the error.

To avoid this, you can 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'); });

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, which makes your code more intuitive and readable to avoid getting race conditions where you get confused 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'); });

When using async/await the code reads like synchronous and it's easier to think about which part runs when.

This helps us to avoid returning a response, before the promise has completely resolved and returning another response after, which would cause the "Cannot set headers after they are sent to the client" error.

Join my newsletter

I'll send you 1 email a week with links to all of the articles I've written that week

Buy Me A Coffee