Error: Can't Set Headers After They Are Sent to the Client

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

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)

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client - Ayuda no se porque sucede eso

after if-else block, you again try to send response.By putting return after sending response in each block, you can fix your problem or other simple way, just comment res.send("recibido").
simple way is to just comment res.send("recibido")

you can write your code this way:

router.post('/', (req, res) => {
const {titulo, director, year, rating} = req.body;
if (titulo && director && year && rating) {
const id = movies.length + 1;
const newMovie = {...req.body, id};
movies.push(newMovie);
res.json(movies);
} else {
res.status(500).json({error: 'Ha Ocurrido un error'});
}
// res.send('recibido');
});

module.exports = router;

Can't set headers after they are sent to the client [ERR_HTTP_HEADERS_SENT]

This error comes from attempting to send more than one response to the same http request.

You have res.send(find[i].result[j]); inside a for loop and you do not stop the inner loop after sending a response.

Thus, this code is capable of attempting to send multiple responses to the same request which you cannot do.

It's unclear from the code exactly what the desired solution is. If you only want to send the first response, then you can close the db and return after you send a response which will terminate both for loops.

If you intend to send multiple pieces of data, then accumulate the data you want to send in an array and send all the data once after all the loops are done.


If you're trying to send an array of all matching results, you can do this:

app.post('/', (req, res) => {
print(req, res)
})

function print(req, res) {
MongoClient.connect(url, function(err, db) {
if (err) {
console.log(err);
res.sendStatus(500);
return;
}
var dbo = db.db("cryptoDb");
dbo.collection("coinTable").find({}).toArray(function(err, find) {
if (err) {
console.log(err);
res.sendStatus(500);
db.close();
return;
}

const id = Capitalize(req.body.coinName);
const idUpper = id.toUpperCase();
const results = [];
for (let findItem of find) {
for (let j = 0; j < 100; j++) {
if (findItem.result[j].name == id || findItem.result[j].symbol == idUpper) {
results.push(findItem.result[j]);
}
}
}
res.send(results);
if (!results.length) {
console.log("No results");
}
db.close();
});
});

function Capitalize(s) {
return s[0].toUpperCase() + s.slice(1).toLowerCase();
}
}

Other Notes:

  1. I changed the if (err) { ... } handling on your database call to actually send an error response. All paths through your request handler need to send a response or cause a response to be sent.

  2. The hard coded loop from 0 to 99 is a bit odd as you don't check if the .result array actually has that many entries in it. That could result in a run-time error if the data isn't exactly how you are expecting it.

  3. You don't have any validation of the req.body data you are expecting. All data arriving from the user should be validated before assuming it is what you are expecting.

How to fix the cannot set headers after they are sent to the client error in node?

In your authenticate functions, you forgot to add an else statement to if (mycookie).

Unauthorized will therefore always be sent, which is clearly the reason why you get unauthorized with a good cookie, and then as unauthorized as already been sent, the error you describe will be throw when getUser tries to sent the http response.

Wrap return res.sendStatus(401); in an else statement and it should work fine.

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

you need to return your error response once an error occurred or otherwise your function will keep running and executing the below code even after the error.

  '/add/grade',
[
check('name', 'grade name is require')
.not()
.isEmpty()
],
auth,
admin,
(req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(400).send({ errors: errors.array() });

const grade = new Grade(req.body);

grade.save((err, doc) => {
if (err) return res.status(400).send({ success: false, err });
return res.status(200).send({
success: true,
grade: doc,
msg: 'Grade add successfully'
});
});
}
);

because if an error occurs or any validation is failed the API sends the response but is not returned so the function keeps on going and executes all other code below it.

As you should know that in an HTTP request response can only be sent once and when the function again sends the response after an error it shows you that cannot send response headers after they are sent to the client.

Hope this helps. GOOD LUCK :)

How do you solve the Cannot set headers after they are sent to the client error in node js?

There are two ways of using promises. Either you use the then/catch callbacks or you can use async/await to allow you to write them synchronously.

then/catch method

// Some code before promise

somePromise.then(() => {
// Some code after promise action is successful
}).catch(err => {
// Some code if promise action failed
})

// Some code after promise definition you think should run after the above code
// THIS IS WHAT IS HAPPENING WITH YOUR CODE

async/await method

// Some code before promise
await somePromise;
// Some code after promise action is successful

The latter approach was introduces to avoid the callback hell problem and it seems that's where your error is arising from.

When using callback callbacks you must make sure that nothing is defined after the promise definition else it will run before the promise resolves (Which is counter-intuitive since placing code B after code B should make A run before B)

Your error is because your callbacks are probably running AFTER the response has been sent and express does not allow you to send multiple responses for a request.
You should make sure that where ever res.send or res.json is being called exist within the callback.

This article should help you understand promises much better...

Hope this helps...



Related Topics



Leave a reply



Submit