Error: Can't set headers after they are sent to the client
Asked Answered
T

49

1214

I'm fairly new to Node.js and I am having some issues.

I am using Node.js 4.10 and Express 2.4.3.

When I try to access http://127.0.0.1:8888/auth/facebook, i'll be redirected to http://127.0.0.1:8888/auth/facebook_callback.

I then received the following error:

Error: Can't render headers after they are sent to the client.
    at ServerResponse.<anonymous> (http.js:573:11)
    at ServerResponse._renderHeaders (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/patch.js:64:25)
    at ServerResponse.writeHead (http.js:813:20)
    at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/auth.strategies/facebook.js:28:15
    at /home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:113:13
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/strategyExecutor.js:45:39)
    at [object Object].pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:32:3)
    at [object Object].halt (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:29:8)
    at [object Object].redirect (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/authExecutionScope.js:16:8)
    at [object Object].<anonymous> (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/auth.strategies/facebook.js:77:15)
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:195:11)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
    at param (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:189:13)
    at pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:191:10)
    at Object.router [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:197:6)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
    at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7)
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 next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:150:23)
    at param (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:189:13)
    at pass (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:191:10)
    at Object.router [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/middleware/router.js:197:6)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
    at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7)
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:150:23)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
    at Object.auth [as handle] (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect-auth/lib/index.js:153:7)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
    at HTTPServer.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:211:3)
    at Object.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:105:14)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
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:150:23)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:207:9)
    at HTTPServer.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:211:3)
    at Object.handle (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:105:14)
    at next (/home/eugene/public_html/all_things_node/projects/fb2/node_modules/connect/lib/http.js:198:15)
    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

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)

The following is my code:

var fbId= "XXX";
var fbSecret= "XXXXXX";
var fbCallbackAddress= "http://127.0.0.1:8888/auth/facebook_callback"

var cookieSecret = "node";     // enter a random hash for security

var express= require('express');
var auth = require('connect-auth')
var app = express.createServer();


app.configure(function(){
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.cookieParser());
    app.use(express.session({secret: cookieSecret}));
    app.use(auth([
        auth.Facebook({
            appId : fbId,
            appSecret: fbSecret,
            callback: fbCallbackAddress,
            scope: 'offline_access,email,user_about_me,user_activities,manage_pages,publish_stream',
            failedUri: '/noauth'
        })
    ]));
    app.use(app.router);
});


app.get('/auth/facebook', function(req, res) {
  req.authenticate("facebook", function(error, authenticated) {
    if (authenticated) {
      res.redirect("/great");
      console.log("ok cool.");
      console.log(res['req']['session']);
    }
  });
});

app.get('/noauth', function(req, res) {
  console.log('Authentication Failed');
  res.send('Authentication Failed');
});

app.get('/great', function( req, res) {
  res.send('Supercoolstuff');
});

app.listen(8888);

May I know what is wrong with my code?

Technics answered 12/8, 2011 at 15:21 Comment(3)
simple answer from visionmedia: github.com/visionmedia/express/issues/634Fearfully
Google sent me to this question, but newer versions of ExpressJS have res.headersSent boolean which can be used to check if safe to set/send headersVogeley
For others troubleshooting this error: In case you use wildcards in your routing, make sure to put such routes after any other routes that would be caught by them.Oryx
M
1621

The res object in Express is a subclass of Node.js's http.ServerResponse (read the http.js source). 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.

Comprehensive list of Node.js/Express response methods and when they must be called:

Response must be in Head and remains in Head:

  1. res.writeContinue()
  2. res.statusCode = 404
  3. res.setHeader(name, value)
  4. res.getHeader(name)
  5. res.removeHeader(name)
  6. res.header(key[, val]) (Express only)
  7. res.charset = 'utf-8' (Express only; only affects Express-specific methods)
  8. res.contentType(type) (Express only)

Response must be in Head and becomes Body:

  1. res.writeHead(statusCode, [reasonPhrase], [headers])

Response can be in either Head/Body and remains in Body:

  1. res.write(chunk, encoding='utf8')

Response can be in either Head/Body and becomes Finished:

  1. res.end([data], [encoding])

Response can be in either Head/Body and remains in its current state:

  1. res.addTrailers(headers)

Response must be in Head and becomes Finished:

  1. return next([err]) (Connect/Express only)
  2. Any exceptions within middleware function(req, res, next) (Connect/Express only)
  3. res.send(body|status[, headers|status[, status]]) (Express only)
  4. res.attachment(filename) (Express only)
  5. res.sendfile(path[, options[, callback]]) (Express only)
  6. res.json(obj[, headers|status[, status]]) (Express only)
  7. res.redirect(url[, status]) (Express only)
  8. res.cookie(name, val[, options]) (Express only)
  9. res.clearCookie(name[, options]) (Express only)
  10. res.render(view[, options[, fn]]) (Express only)
  11. res.partial(view[, options]) (Express only)
Mint answered 12/8, 2011 at 15:21 Comment(9)
Yep, check for calling next() or other cb twice.Shanika
Express links seems deadToggle
also watch out for this classic mistake: res.redirect() doesn't stop statement execution... so return after it. Otherwise other code could be executed which could unintentiallly cause the famous header error. Thanx for the explanation!Collete
Its usually a good idea to use return at the end of your callback to avoid thisBirthmark
I made a very small error in my middleware, I didnt return before next(), thanks this pointed me to the error!Portiaportico
the express documentation shows "send" for Response, but doesn't mention "write" at all...Verbify
Ensure that the next function isn't executed before the send. I got this error because I did that and express sent its error message before I run response.sendSr
What about checking: res.finished?Whittington
for me I removed the next() for the error to disappearPouf
D
235

Some of the answers in this Q&A are wrong. The accepted answer is also not very "practical", so I want to post an answer that explains things in simpler terms. My answer will cover 99% of the errors I see posted over and over again. For the actual reasons behind the error take a look at the accepted answer.


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.

This error message:

Error: Can't set headers after they are sent.

usually happens when you send several responses for one request. Make sure the following functions are called only once per request:

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

(and a few more that are rarely used, check the accepted answer)

The route callback will not return when these res functions are called. It will continue running until it hits the end of the function or a return statement. If you want to return when sending a response you can do it like so: return res.send().


Take for instance this code:

app.post('/api/route1', function(req, res) {
  console.log('this ran');
  res.status(200).json({ message: 'ok' });
  console.log('this ran too');
  res.status(200).json({ message: 'ok' });
}

When a POST request is sent to /api/route1 it will run every line in the callback. A Can't set headers after they are sent error message will be thrown because res.json() is called twice, meaning two responses are sent.

Only one response can be sent per request!


The error in the code sample above was obvious. A more typical problem is when you have several branches:

app.get('/api/company/:companyId', function(req, res) {
  const { companyId } = req.params;
  Company.findById(companyId).exec((err, company) => {
      if (err) {
        res.status(500).json(err);
      } else if (!company) {
        res.status(404).json();      // This runs.
      }
      res.status(200).json(company); // This runs as well.
    });
}

This route with attached callback finds a company in a database. When doing a query for a company that doesn't exist we will get inside the else if branch and send a 404 response. After that, we will continue on to the next statement which also sends a response. Now we have sent two responses and the error message will occur. We can fix this code by making sure we only send one response:

.exec((err, company) => {
  if (err) {
    res.status(500).json(err);
  } else if (!company) {
    res.status(404).json();         // Only this runs.
  } else {
    res.status(200).json(company);
  }
});

or by returning when the response is sent:

.exec((err, company) => {
  if (err) {
    return res.status(500).json(err);
  } else if (!company) {
    return res.status(404).json();  // Only this runs.
  }
  return res.status(200).json(company);
});

A big sinner is asynchronous functions. Take the function from this question, for example:

article.save(function(err, doc1) {
  if (err) {
    res.send(err);
  } else {
    User.findOneAndUpdate({ _id: req.user._id }, { $push: { article: doc._id } })
    .exec(function(err, doc2) {
      if (err) res.send(err);
      else     res.json(doc2);  // Will be called second.
    })

    res.json(doc1);             // Will be called first.
  }
});

Here we have an asynchronous function (findOneAndUpdate()) in the code sample. If there are no errors (err) findOneAndUpdate() will be called. Because this function is asynchronous the res.json(doc1) will be called immediately. Assume there are no errors in findOneAndUpdate(). The res.json(doc2) in the else will then be called. Two responses have now been sent and the Can't set headers error message occurs.

The fix, in this case, would be to remove the res.json(doc1). To send both docs back to the client the res.json() in the else could be written as res.json({ article: doc1, user: doc2 }).

Doha answered 6/1, 2018 at 1:10 Comment(3)
You are inside an asynchronous function, and must return the res.jsonCoussoule
My issue was using res.send in for loop.Inerrable
Thank you so much for this explanation Mika. I had product().findById().then().then().catch(). Both .then() methods each had a res.status().json in them. Removing one solved the can't set headers after they are sent to the client issue.Rattlepate
D
160

I ran into this error as well for a while. I think (hope) I've wrapped my head around it, wanted to write it here for reference.

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 (At least with the current npm install connect, which looks quite different from the one github as of this post). When the server gets a request, it iterates over the stack, calling the (request, response, next) method.

The problem is, if in one of the middleware items writes to the response body or headers (it looks like it's either/or for some reason), but doesn't call response.end() and you call next() then as the core Server.prototype.handle method completes, it's going to notice that:

  1. there are no more items in the stack, and/or
  2. that response.headerSent is true.

So, it throws an error. But the error it throws is just this basic response (from the connect http.js source code:

res.statusCode = 404;
res.setHeader('Content-Type', 'text/plain');
res.end('Cannot ' + req.method + ' ' + req.url);

Right there, it's calling res.setHeader('Content-Type', 'text/plain');, which you are likely to have set in your render method, without calling response.end(), something like:

response.setHeader("Content-Type", "text/html");
response.write("<p>Hello World</p>");

The way everything needs to be structured is like this:

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);

Problematic Middleware

var problemMiddleware = function(request, response, next) {
  response.setHeader("Content-Type", "text/html");
  response.write("<p>Hello World</p>");
  next();
};

The problematic middleware sets the response header without calling response.end() and calls next(), which confuses connect's server.

Deuteron answered 17/10, 2011 at 3:38 Comment(2)
+1 This is a great explanation, but what about the case when you use res.redirect()? I frequently run into this problem when the middleware is trying to redirect based on some condition. Should middleware not redirect, per your "Good Middleware" example?Drummer
You know I have this exact problem due to what you call a problematic middleware, however I need a case where I return response but would like to do further processing in a separate controller as part of the chain, how do I go about suppressing this error?Constitutional
D
74

I had this same issue and realised it was because I was calling res.redirect without a return statement, so the next function was also being called immediately afterwards:

auth.annonymousOnly = function(req, res, next) {
    if (req.user) res.redirect('/');
    next();
};

Which should have been:

auth.annonymousOnly = function(req, res, next) {
    if (req.user) return res.redirect('/');
    next();
};
Dactyl answered 14/2, 2015 at 13:2 Comment(2)
Can't get to next() if you return.Sulfamerazine
@Sulfamerazine I don't understand your point. The intention was to not call next if a redirect had been called. Calling next after a return wasn't intended.Dactyl
P
53

Lots of people hit this error. It's a confusing this with async processing. Most likely some of your code is setting headers in the first tick and then you are running an async callback in a future tick. In between, the response header gets sent, but then further headers (like a 30X redirect) try to add extra headers, but it's too late since the response header has already been transmitted.

I'm not sure exactly what's causing your error, but look at any callbacks as potential areas to investigate.

One easy tip to simplify your code. Get rid of app.configure() and just call app.use directly in your top level scope.

See also the everyauth module, which does Facebook and a dozen or so other 3rd party authentication providers.

Passionless answered 12/8, 2011 at 18:24 Comment(2)
A 30X redirect is an HTTP response code. w3.org/Protocols/rfc2616/rfc2616-sec10.html Codes 300-399 are different variations of redirection, with 302 and 301 being commonly used to send the client to an alternate URL. When you do response.redirect(...) in node, a 30X redirect header will be sent in the response.Passionless
Ohhhh. I was imagining 30 redirects in a row or somethingGree
I
24

This type of error you will get when you pass statements after sending a response.

For example:

res.send("something response");
console.log("jhgfjhgsdhgfsdf");
console.log("sdgsdfhdgfdhgsdf");
res.send("sopmething response");

Will result in the error you are seeing, because once the response has been sent, the following res.send will not be executed.

If you want do anything, you should do it before sending the response.

Instrumental answered 28/9, 2016 at 13:21 Comment(0)
T
23

error find by itself after a RND :

1) my error code :

return res.sendStatus(200).json({ data: result });

2) my success code

return res.status(200).json({ data: result });

the difference is that i used sendStatus() instead of status().

Timbal answered 19/12, 2019 at 10:50 Comment(2)
why you were using the sendStatus in the first place?Rusel
Basically to send the status for frontend.Timbal
C
21

I boiled my head over this issue and it has happened due to a careless mistake on handling the callbacks. non returned callbacks cause the response to be set twice.!

My program had a code which validate request and query the DB. after validating if error is there, I was calling back the index.js with the validation errors . And if validation passes it goes ahead and hit the db with success/failure.

    var error = validateRequestDetails("create",queryReq);
    if (error)
        callback(error, null);
   else
    some code 
    callback(null, success);

What was happening is : Incase validation fails the callback get called and response get set. But not returned. So it still continues the method goes to db and hit success/failure . It calls the same callback again causing the response to be set twice now.

So solution is simple, you need to 'return' the callback so that the method don't continue executing, once the error has occurred and hence set the response object once

  var error = validateRequestDetails("create",queryReq);
    if (error)
        callback(error, null);
        return;
    else
       some code 
       callback(null, success);
Citrate answered 4/7, 2015 at 5:22 Comment(1)
Thanks! This turned out to be my problem too. Just did a ctrl+f and found a callback(...) without a return; after it which was eventually causing res.send(...) to be called twice.Entoblast
C
20

I simply add the return keyword like: return res.redirect("/great"); and it worked!

Countersignature answered 13/11, 2019 at 16:33 Comment(0)
W
17

This error happens when you send 2 responses. For example :

if(condition A)
{ 

      res.render('Profile', {client:client_});

}

if (condition B){

      res.render('Profile', {client:client_});
    }
  }

Imagine if for some reason condition A and B are true so in the second render you'll get that error

Westley answered 7/10, 2019 at 10:49 Comment(0)
U
13

Sometimes you may get this error when you try to call next() function after res.end or res.send , try to delete if you have next() after res.send or res.end in your function. Note: here next() means after responding to the client with your response(i.e res.send or res.end) you are still trying to execute some code to respond again so it is not legal.

Example :

router.get('/',function (req,res,next){
     res.send("request received");
     next(); // this will give you the above exception 
});

remove next() from above function and it will work.

Unwinking answered 8/3, 2017 at 11:54 Comment(1)
Indeed, this was my case, a lingering next() call in a middleware was causing the issue. It took me almost an hour to realize that...Wildlife
H
13

If you are using callback functions use return after the err block. This is one of the scenarios in which this error can happen.

userModel.createUser(data, function(err, data) {
    if(err) {
      res.status = 422
      res.json(err)
      return // without this return the error can happen.
    }
    return res.json(data)
  })

Tested on Node version v10.16.0 and express 4.16.4

Highroad answered 5/6, 2019 at 8:24 Comment(0)
W
8

there is something else that cause this error and it is when you do not add return keyword in front of res.send, res.json, etc...

Wollongong answered 16/7, 2020 at 23:0 Comment(0)
R
7

Please check if your code is returning multiple res.send() statements for a single request. Like when I had this issue....

I was this issue in my restify node application. The mistake was that

switch (status) {
    case -1:
      res.send(400);
    case 0:
      res.send(200);
    default:
      res.send(500);
}

I was handling various cases using switch without writing break. For those little familiar with switch case know that without break, return keywords. The code under case and next lines of it will be executed no matter what. So even though I want to send single res.send, due to this mistake it was returning multiple res.send statements, which prompted

error: can't set headers after they are sent to the client.

Which got resolved by adding this or using return before each res.send() method like return res.send(200)

switch (status) {
    case -1:
      res.send(400);
      break;
    case 0:
      res.send(200);
      break;
    default:
      res.send(500);
      break;
}
Rockafellow answered 12/1, 2019 at 6:13 Comment(0)
G
6

A newer version of Node supports res.headersSent boolean expression. You can use it to validate whether you already sent a response:

if (!res.headersSent) // if doesn't sent yet
    res.status(200).send({ "message": "This is a message" })

Note! Although this works and answers the question, it's not the right way to solve the problem, and is not recommended!

Sending a response more than once indicates that you have a problem in your code that should be fixed (It's the same as using two return statements, one after another, in your function. it's a bug).

Gronseth answered 29/9, 2021 at 11:15 Comment(0)
K
5

In my case it was a 304 response (caching) that was causing the issue.

Easiest solution:

app.disable('etag');

Alternate solution here if you want more control:

http://vlasenko.org/2011/10/12/expressconnect-static-set-last-modified-to-now-to-avoid-304-not-modified/

Karol answered 17/5, 2014 at 0:5 Comment(3)
In my case also 304 response. I a m using Fibers for processing. Any way your answer helps a lot. thank youBeatification
Can anyone explain what the implications are for removing the etag header?Mertens
ETags allow the server to not send content that hasn't changed. Turning it off disables this feature. The ETag wikipedia entry (en.wikipedia.org/wiki/HTTP_ETag) has a lengthier explanation.Karol
Q
5

For anyone that's coming to this and none of the other solutions helped, in my case this manifested on a route that handled image uploading but didn't handle timeouts, and thus if the upload took too long and timed out, when the callback was fired after the timeout response had been sent, calling res.send() resulted in the crash as the headers were already set to account for the timeout.

This was easily reproduced by setting a very short timeout and hitting the route with a decently-large image, the crash was reproduced every time.

Quidnunc answered 19/5, 2015 at 12:56 Comment(1)
how did you handle the timeout to avoid this?Unloosen
C
5

In my case this happened with React and postal.js when I didn't unsubscribe from a channel in the componentWillUnmount callback of my React component.

Caucasia answered 2/6, 2015 at 10:12 Comment(0)
E
5

Please search if in your app.get to not set status before res.send("your result");

I just removed :

res.sendStatus(200);

and response works after that !!!

res.send("your result");
Eisenstark answered 14/1, 2021 at 16:40 Comment(0)
V
4

Just leaned this. You can pass the responses through this function:

app.use(function(req,res,next){
  var _send = res.send;
  var sent = false;
  res.send = function(data){
    if(sent) return;
    _send.bind(res)(data);
    sent = true;
};
  next();
});
Velasco answered 5/11, 2015 at 7:28 Comment(0)
S
4

This happens when response was delivered to client and again you are trying to give response. You have to check in your code that somewhere you are returning response to client again which causes this error. Check and return response once when you want to return.

Sebbie answered 12/7, 2017 at 13:45 Comment(0)
U
4

I had the same issue. For me i had 2 res.json(event) was giving this error to me.

res.json(savedEvent);
res.json({ event });

We should pass only single response will work.

res.json(event);
Unavoidable answered 14/11, 2022 at 13:39 Comment(0)
T
3

Add this middlware and it will work

app.use(function(req,res,next){
 var _send = res.send;
var sent = false;
res.send = function(data){
    if(sent) return;
    _send.bind(res)(data);
    sent = true;
};
next();
});
Tailor answered 28/4, 2017 at 4:26 Comment(0)
A
3

If you din't get help from above : for noobs The reason behind this error is sending request multiple times let us understand from some cases:- 1. `

module.exports = (req,res,next)=>{
        try{
           const decoded  = jwt.verify(req.body.token,"secret");
           req.userData = decoded;
           next();
        }catch(error){
            return res.status(401).json({message:'Auth failed'});
        }
        next();   
        }

` in the above calling next() twice will raise an error

  1. router.delete('/:orderId', (req, res, next) => { Order.remove({_id:req.params.orderId},(err,data)=>{ if(err){ **res.status(500).json(err);** }else{ res.status(200).json(data); } *res.status(200).json(data);* }) })

here respond is send twice check whether you already sent a response

Allegiance answered 28/4, 2018 at 5:49 Comment(0)
V
3

It is very likely that this is more of a node thing, 99% of the time it's a double callback causing you to respond twice, or next()ing twice etc, damn sure. It solved my problem was using next() inside a loop. Remove the next() from the loop or stop calling it more than one times.

Verla answered 22/2, 2019 at 17:51 Comment(1)
I had the same error and it was caused because within the same middleware function I was calling two functions and each of them called next(). I fixed the error by creating a second middleware function and moving one of those functions into it so there was only a single next() call within each middleware function. This is the commit that solved the issue: github.com/DataHighway-DHX/faucet/commit/…Dichasium
D
3

The problem was exist from /auth/facebook route to make things ease to understand, once that you sent a response already from the client, you must NOT set any other functions below for next successor block, it is also related on being Synchronous of JavaScript,

for deep understanding, it is looks like this code;

async function getRequest(){
   let data = await API.get();
   return data;
   let json = data.json(); // will not read this line
}

on your case, console.log("ok cool."); and console.log(res['req']['session']) must be put before res.redirect("/great")

enter image description here

Hope it make sense, Welcome :)

Deil answered 12/6, 2021 at 9:44 Comment(0)
C
3

If you uses two of res.end() function in one api call, this error shows

for example

  app.post("/auth", function (request, res) {
    var username = request.body.username;
    var password = request.body.password;
    if (username && password) {
      let sql =
        "SELECT username, worker_name, worker_surname, id FROM workers where username = ? AND password=?";
      con.query(sql, [username, password], function (error, results, fields) {
        if (results.length > 0) {
          res.status(200).send(results);
          res.end();
  
        }
        res.status(404).send("Incorrect Username and/or Password!");
      });
    } else {
      res.send("Please enter Username and Password!");
    }
    res.end();

  });
Collaboration answered 27/8, 2021 at 7:33 Comment(0)
P
3

sometimes only writing res.status(200).json({success: 'user authenticated'); is not enough. For hours , i found we have to return return response sometimes. Like this

return res.status(200).json({success: 'user authenticated');

so that It can terminate whenever in some conditional statement and doesn't run other .

Plectrum answered 19/5, 2022 at 5:5 Comment(1)
Yes, for nextjs project, the API is better have a return keyword or your API response.Swayder
A
2

I got a similar error when I tried to send response within a loop function. The simple solution was to move the

res.send('send response');

out of the loop since you can only send response header once.

https://www.tutorialspoint.com/nodejs/nodejs_response_object.htm

Admire answered 25/10, 2019 at 17:29 Comment(0)
H
2

Check your code. For me, I used res.status twice in the same if statement. First one set the header status and the second one tried to change it, which caused the problem.

Hoarhound answered 1/5, 2021 at 8:45 Comment(1)
thanks man. but what is the difference between res.end() and res.send(), I think both terminate the api call. res.send() sends the response and stop the function while res.end() only terminate the function without sending response . is that true?Valetudinary
G
1

In Typescript, my issue was I didn't close the websocket connection after receiving a message.

WebSocket.on("message", (data) => {
    receivedMessage = true;
    doSomething(data);
    localSocket.close(); //This close the connection, allowing 
});
Gree answered 19/3, 2018 at 20:14 Comment(0)
L
1

I had this issue when I was nesting promises. A promise inside of a promise would return 200 to the server, but then the outer promise's catch statement would return a 500. Once I fixed this, the problem went away.

Laurelaureano answered 18/6, 2018 at 23:25 Comment(1)
how exactly did you fix this? I have the same issue with promises. I cant avoid nesting them... so how do i stop execution at return statement?Florencio
A
1

In my case it happens due to multiple callbacks. I have called next() method multiple time during the code

Aludel answered 9/7, 2018 at 6:20 Comment(0)
S
1

Came here from nuxt, the problem was in the component's asyncData method, I forgot to return promise which was fetching data and setting header there.

Swamy answered 24/8, 2018 at 14:5 Comment(0)
R
1

I had the same problem which was caused by mongoose.

to fix that you must enable Promises, so you can add : mongoose.Promise = global.Promise to your code,which enables using native js promises.

other alternatives to this soloution is :

var mongoose = require('mongoose');
// set Promise provider to bluebird
mongoose.Promise = require('bluebird');

and

// q
mongoose.Promise = require('q').Promise;

but you need to install these packages first.

Romansh answered 11/2, 2020 at 16:28 Comment(0)
S
1

Process.env does not change, so it must not be used for accessing per-request environment variables whose values may change on a per-request basis. So, if the user spawns an application process, but not as part of handling a request, then that application process will not have per-request environment variables stored inside OS-level environment variables. So, use this code to store process env and your program run successfully.

    const port = process.env.PORT || 2000;
    
    app.listen(port,()=>{
        console.log("Server running at port 2000");
    })
Sharpie answered 5/8, 2020 at 13:33 Comment(0)
A
1

In my case, this is recurring when I don't make a function that is running against a mongodb schema an async function like this technicianAuthSchema.methods.matchPasswords = function(password) { return await bcrypt.compare( password, this.password ); }; I get this Logged error: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client instead of technicianAuthSchema.methods.matchPasswords = async function(password) { return await bcrypt.compare( password, this.password ); }; It is asynchronous because the this.password is coming from the object this function is running against which we are pulling from the database.

Austrasia answered 22/4, 2021 at 9:46 Comment(0)
U
1

I had the issue this is what I was doing

const user  = await User.findOne({_id: req.params.id})

so I had to change findOne to findById and it did the trick for me

const user = await User.findById(req.params.id)
Unpromising answered 5/4, 2022 at 17:12 Comment(0)
I
1

I got the same error and found my solution was to change all of my sendStatus lines of code to status.

// old
res.sendStatus(200);

// new 
res.status(200);
Impressment answered 6/5, 2022 at 1:19 Comment(0)
T
1

In my case, I had to add the .then() method of Promise to chain on the response. So my code looks like below:

 app.post(`${api}/categories`, (req, res) => {
const category = new Category({
    ....
});
category.save().then(c => {
    res.status(201).json(c)
}).catch((err) => {
    res.status(500).json({
        ...
    })
});

})

Thompson answered 5/7, 2022 at 0:16 Comment(0)
F
1

I faced the error for a couple of days and found out that it was my jwt that got expired, in that scenerio it could not set headers.

check your jwt expiration date

Fionafionna answered 26/9, 2022 at 7:7 Comment(0)
C
1

I had the same error using postman. I noticed that the request body (data) was improperly formatted. The error was pointing to the middleware I passed on the routes. When I remove one middleware, it then means to the next.

Cathiecathleen answered 20/10, 2022 at 16:13 Comment(0)
N
0

My issue was that I had a setInterval running, which had an if/else block, where the clearInterval method was inside the else:

      const dataExistsInterval = setInterval(async () => {
        const dataExists = Object.keys(req.body).length !== 0;
        if (dataExists) {
          if (!req.files.length) {
            return res.json({ msg: false });
          } else {
              clearInterval(dataExistsInterval);
            try {
            . . .

Putting the clearInterval before the if/else did the trick.

Nunez answered 14/1, 2020 at 13:49 Comment(0)
Z
0

In my case, In a loop, I put res.render() so might have been tried to call multiple times.

Zigzag answered 20/2, 2020 at 4:23 Comment(0)
T
0

In my case, it was a global interceptor that was setting the no-cache header.

Tutto answered 21/6, 2022 at 9:9 Comment(0)
M
0

Evidently this can happen for a multitude of reasons. Many are complex, but my case was a pretty simple mistake.

Check that you have the right form method. The default is GET, and I somehow forgot to specify. As one can imagine, my GET route logic did a poor job handling the req.body data that was designed to be parsed by my POST route logic.

Marginal answered 30/6, 2022 at 2:57 Comment(0)
O
0

Do not use multiple res in one api. Just use res one time and this problem will be solved.

Overcritical answered 7/11, 2023 at 9:9 Comment(0)
U
0

The issue is, multiple modification of header of res(Response) is happening in the code. Which isn't allowed because express sends the data to client when the first invocation happens. So the second one fails. If you can bypass to having only 1 header per case, it will resolve the issue. It can be done Via conditional statements or returning once headers are assigned or not setting errors until you have completely processed till the end of code (whichever applies best)

I was getting the same Error "ERR_HTTP_HEADERS_SENT" for the following code:

const createPrice = async function (request, response) {
  const data = request.body;
  var maxID = 9999;
  const result = await pool.query("SELECT MAX(id) FROM pricing");
  maxID = result.rows[0].max + 1;
  pool.query(
    "Insert into pricing (id, price, discounts) values ($1, $2, $3) RETURNING *",
    [maxID, data.price, data.discounts,],
    (error, results) => {
      if (error) {
        throw error;
      }
      response.status(201).send(`Rate Card ID: ${maxID} Created`);
          }
        }
      );
    };

To me it seems like the issue was I am handling the error in my middleware, so what was happening was the body of the response was getting set in 2 places, first in the throw error; and secondly in response.status(201).send();

I think the minimum change required to get my code to work was to put an else and put my response.send() inside it. So only one of the two setting of data to request works.

Somehow, putting a return or headerSent check alone didn't work for me. But I ended up using a combination of above solutions for better handling of the issue. Here, my final change:

(error, results) => {
  if (error) {
    throw error;
  } else if (!response.headersSent) {
    // if doesn't sent yet
    return response
      .status(201)
      .send(`Rate Card ID: ${data.maxID} Created`);
  }
}
Unclench answered 14/11, 2023 at 7:44 Comment(0)
F
-1

All I had to do in case of this error was res.end().

 auth.annonymousOnly = function(req, res, next) {
 // add other task here   
   res.end();    
  };

The other problem you could be facing is there is code after res.json and res. write. In this case, you need to use return to stop execution after that.

 auth.annonymousOnly = function(req, res, next) {

  if(!req.body.name)
  {
    res.json({error:"some error"});
    return;
  }
  let comp = "value"; // this is the code after res.json which may cause some problems so you have to use return 
};
Federica answered 7/9, 2018 at 10:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.