Seeing the “Cannot set headers after they are sent” error in Express.js can be frustrating, but solving it is easier than it seems. This guide explains exactly why this error happens and shows step-by-step how to fix it fast, so we can keep our Node.js applications running smoothly and avoid unexpected bugs.
Understanding the HTTP and Express Module
We know that the HTTP protocol establishes a client-server protocol where the client which is generally a Web Browser communicates with the server by exchanging individual messages. Node.js has a built-in HTTP module that helps in establishing such communication using JavaScript over the HTTP protocol.
The messages sent by the client, are called requests and the messages sent by the server as an answer are called responses. The HTTP module provides low-level API for stream handling and message parsing. A field within an HTTP request or response, known as an HTTP header, transmits extra information and contextual data regarding the request or response.
The client makes a request to the server. The request gets wrapped in a request object and sent to the server. This is where the Node.js HTTP module comes in. The HTTP module helps create a web server that listens to events. On receiving the request object from the client, the message is parsed, and then an appropriate response object is created setting the response headers also. The HTTP module sends in the response object to the client and the HTTP request-response cycle ends.
The following code will help you better understand the HTTP cycle.
const http = require('http')
const app = http.createServer()
app.on('request', (req, res) => {
if (req.url === '/') {
res.writeHead(200, {'content-type': 'text/html'})
res.write('<h1>Hello from Server</h1>')
res.end()
}
})
app.listen(3000)
In the above code, the HTTP module creates a server and listens to request events on port 3000. On receiving a request on the homepage i.e http://localhost:3000 a response object is created with headers set using the writeHead method and the body is an H1 tag set using the write method. The end method ends the HTTP cycle.
Using the HTTP module can get tedious so the Express.js package was introduced. Express is a wrapper around the HTTP module that helps in creating routes and middleware easily. A middleware function serves as an intermediary between the request and response objects, governing the exchange of data.
Express determines the type of middleware based on the number of parameters provided. Route middleware, for instance, utilizes a callback that includes the request and response parameters. Custom middleware usually receives the request, response, and next parameters. Finally, an error handler typically accepts the error, request, response, and next parameters.
Express works similarly to the HTTP module however it ends the HTTP cycle when the following method is used with the response:
- json()
- send()
- sendStatus()
- redirect()
- render()
Why Express produces this Error
If we ever send more than one such response method for a single request or HTTP cycle using express, the error, “Cannot set headers after they are sent to client” is produced which means we are trying to set the header for a response after it has already been sent to the client or after the HTTP cycle has already ended.
This error is also produced if an express middleware uses the next() method more than once or uses the above-mentioned response methods with the next() method in the same scope. I will explain this error and its solution better with some examples.
Setting up an Express.js project to demonstrate the Error
Open your terminal, create a project folder, initialize a node project inside it, and install the dependencies using the following commands.
mkdir httpServer && cd httpServer
npm init -y
npm install express ejs nodemon
Create a views folder and an index.ejs file inside it
views/index.ejs
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Home Page</title>
</head>
<body>
<h1>This is homepage</h1>
</body>
</html>
index.js
const express = require('express')
const app = express()
app.set('view engine', 'ejs')
app.get('/', (request, response) => {
response.render('index')
})
app.get('/user', (request, response) => {
response.redirect('/')
})
app.listen(3000, () => {
console.log("Server is listening on port 3000");
})
Here we have created a basic express server that listens on port 3000 and defined two routes, one for the homepage and another user. We are also rendering HTML pages using EJS.
Start the server using the command:
nodemon index.js
Now we can move on with the examples.
Example 1:
// index.js
const express = require('express')
const app = express()
app.set('view engine', 'ejs')
app.get('/', (request, response) => {
response.render('index')
})
app.get('/user', (request, response) => {
response.redirect('/')
response.status(200).json({"error": "Some error"})
})
app.listen(3000, () => {
console.log("Server is listening on port 3000");
})
Output:
On line 13 we are already redirecting the request to the home route and ending the HTTP cycle but on line 14 we are again trying to send a response object with status 200 and a JSON body. This violates the HTTP principle and we meet with an error.

Solution: Remove either line 13 or line 14 to remove the error. Alternatively, you can also use a return statement to shadow any code written below it in its scope.
return response.redirect('/')
Example 2
// index.js
const express = require('express')
const app = express()
app.set('view engine', 'ejs')
app.get('/', (request, response) => {
response.render('index')
})
const authUser = (request, response, next) => {
console.log('User authenticated');
next()
response.status(400).json({"key":"value"})
}
app.get('/user', authUser, (request, response) => {
response.status(200).json({"error": "Some error"})
})
app.listen(3000, () => {
console.log("Server is listening on port 3000");
})
In this example, we introduced a custom middleware for the route /user and defined it.
Output:
If we visit http://localhost:3000/user using our browser we are again given the error because in the middleware we use the next() method to go to the next route middleware and then also try to send a response body with status 400 and a JSON.

Solution: The solution to it will be to either completely remove line number 15 or use a condition check to decide which response to send. Alternatively, you can also return from the middleware using return next() to shadow any code written below it in its scope.
Frequently Asked Questions
What does the “Cannot set headers after they are sent to the client” error mean in Express.js?
This error means the application is trying to change response headers or send another response after the first response has already been sent to the client.
Why does this error happen in Express.js applications?
This error usually happens when more than one response is sent for a single request, or when we try to set headers after the response has already been sent.
What are the most common causes of this error?
The most common causes are calling response methods like res.send(), res.json(), or res.end() more than once, or handling asynchronous code in a way that sends multiple responses.
How can we fix the “Cannot set headers after they are sent” error?
To fix this error, we need to make sure only one response is sent for each request and that headers are set before sending the response.
How can we prevent this error when using asynchronous code?
We can prevent this error by checking if the response has already been sent before setting headers or sending a response, and by using return statements to stop code execution after sending a response.
What are some best practices to avoid this error in Express.js?
Some best practices are to use return statements after sending a response, handle errors properly, and use middleware carefully to avoid sending multiple responses.
How can we check if a response has already been sent?
We can check if a response has been sent by using the res.headersSent property, which is true if the response has already been sent to the client.
Can this error happen with middleware functions in Express.js?
Yes, this error can happen if middleware functions are not managed correctly and end up sending multiple responses for the same request.
What should we look for when debugging this error in our code?
We should look for places where response methods are called more than once for the same request, especially inside callbacks or asynchronous functions.
Is it possible to modify headers after sending a response?
No, once a response has been sent, headers cannot be changed or set again, as the HTTP protocol does not allow it.
Conclusion
In this article, we discussed one of the most common errors when working with Express.js, that is “Cannot set headers after they are sent to client” and also saw some practical demonstrations on how to correct and avoid this error. Hope you find this article helpful.
If you are wondering what to read next, then try reading our introductory guide on Express.js.
References
- https://stackoverflow.com/questions/7042340/error-cant-set-headers-after-they-are-sent-to-the-client
- https://developer.mozilla.org/en-US/docs/Web/HTTP