“Can’t set headers after they are sent to the client” error in Express.js – possible solutions

Express is a JavaScript framework for Node.js. It handles a Web application's front end and back-end, calling the appropriate event handlers and making the necessary database conversions by utilizing various Node modules whenever it receives a request from an user. Express is one of the most popular web frameworks out there, downloaded more than 10 million times as of this writing.

The beauty of Express lies in its simplicity: it offers no opinionated work but has just enough to get your job done fast with at least some degree of conciseness, which is perfect for beginners who are not yet familiar with Node or JavaScript and just want something simple and easy to work with.

"Can't set headers after they are sent to the client" is one of the most common errors in Express.js. This error occurs when you sent a response to the client before and then you try to send the same response again. This article is going to show you a few ways you can get rid of "Can't set headers after they are sent to the client" error in Express.js.

"Can't set headers after they are sent to the client" causes

The res object in Express is a subclass of Node.js's http.ServerResponse . You are allowed to call res.setHeader(name, value) as often as you want until you call res.writeHead(statusCode). After writeHead, the headers are baked in and you can only call res.write(data), and finally res.end(data).

The error "Error: Can't set headers after they are sent." means that you're already in the Body or Finished state, but some function tried to set a header or statusCode. When you see this error, try to look for anything that tries to send a header after some of the body has already been written. For example, look for callbacks that are accidentally called twice, or any error that happens after the body is sent.

In your case, you called res.redirect(), which caused the response to become Finished. Then your code threw an error (res.req is null). and since the error happened within your actual function(req, res, next) (not within a callback), Connect was able to catch it and then tried to send a 500 error page. But since the headers were already sent, Node.js's setHeader threw the error that you saw. Typical error message may look like this:

.............. node.js:134 throw e; // process.nextTick error, or 'error' event on first tick ^ Error: Can't set headers after they are sent. at ServerResponse.<anonymous> (http.js:527:11) at ServerResponse.setHeader (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:50:20) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:162:13) at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9) at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:323:9 at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session.js:338:9 at Array.<anonymous> (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/session/memory.js:57:7) at EventEmitter._tickCallback (node.js:126:26)
Code language: JavaScript (javascript)

HTTP uses a cycle that requires one response per request. When the client sends a request (e.g. POST or GET) the server should only send one response back to it.

"Can't set headers after they are sent to the client" error may occur due to one of the following reasons:

  • The source code instructs compiler to send multiple responses to the client. Or multiple res functions were called while processing the same request.
  • Sometimes it happens due to asynchronous behavior of Node.js.
  • Sometimes a process sends a response to the client in the event loop, and once it finishes execution, response will be sent again.

Check for duplicate function calls

The Error: Can't set headers after they are sent. error message usually happens when you send several responses for one request. In order to avoid it, make sure the following functions are called only once per request:

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

Above are the most common response methods that you should check, you can see a comprehensive list of them in https://nodejs.org/docs/latest/api/http.html#http_class_http_serverresponse.

Check for problematic middleware

When you add middleware to connect or express (which is built on connect) using the app.use method, you're appending items to Server.prototype.stack in connect. When the server gets a request, it iterates over the stack, calling the (request, response, next) method.

If in one of the middleware items writes to the response body or headers, but doesn't call response.end() and right after that you call next(), "Can't set headers after they are sent to the client" error may be thrown because response.headerSent is true while there are nothing in the stack anymore.

Below is an example of a good middleware :

// middleware that does not modify the response body var doesNotModifyBody = function(request, response, next) { request.params = { a: "b" }; // calls next because it hasn't modified the header next(); }; // middleware that modify the response body var doesModifyBody = function(request, response, next) { response.setHeader("Content-Type", "text/html"); response.write("<p>Hello World</p>"); response.end(); // doesn't call next() }; app.use(doesNotModifyBody); app.use(doesModifyBody);
Code language: PHP (php)

Redirect without return

One of the common mistake when people make redirects in Express is that they often forget the return statement when calling res.redirect().

// Faulty code auth.annonymousOnly = function(req, res, next) { if (req.user) res.redirect('/'); //ERROR OCCURS HERE next(); };
Code language: JavaScript (javascript)

What you need to do is actually return res.redirect() instead of simply calling it. You may also remove next()

if (req.user) return res.redirect('/');
Code language: JavaScript (javascript)

Faulty conditionals in the code

If your code returns the response based on multiple conditionals, there is a chance that multiple conditions are met, hence multiple responses are sent to the client. See the faulty pseudo-code block below to understand what I mean.

if(someCondition) { await () => { } } await () => { }
Code language: JavaScript (javascript)

Or, with multiple if statements :

if(condition A) { res.render('Profile', {client:client_}); } if (condition B){ res.render('Profile', {client:client_}); } }
Code language: JavaScript (javascript)

Inspect your code carefully, and pay attention to if-else blocks. Better yet, try to return responses when you can (statements after return won't be executed) to avoid Can't set headers after they are sent to the client error.

We hope that the article helped you successfully debugged "Can't set headers after they are sent to the client" error in Express.js, as well as avoid encountering it in the future.

We've also written a few other guides for fixing common JavaScript errors, such as How to fix “nodemon: command not found” and npm: command not found . If you have any suggestion, please feel free to leave a comment below.

Click to rate this post!
[Total: 0 Average: 0]

Leave a Comment