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

Created on 6 Sep 2018  路  3Comments  路  Source: nestjs/nest

I'm trying to stream some data from controller.
Simplified example:

@Get('test')
  public async test(@Res() res) {
    res.setHeader('Content-Type', 'text/event-stream');
    for (let i = 0; i < 10; i++) {
      res.write(Math.random() + '\n');
      // if service throws exception
      // throw new HttpException('Baddy', 403);
      // nest trying to set header but we already in body after res.write
      this.testService.process();
    }
    res.end();
  }

Basically if exception happens after body already written following error thrown:

0.019643958486124546
(node:45041) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:470:11)
    at ServerResponse.header (/Users/sasha/Dev/my_project/node_modules/express/lib/response.js:767:10)
    at ServerResponse.send (/Users/sasha/Dev/my_project/node_modules/express/lib/response.js:170:12)
    at ServerResponse.json (/Users/sasha/Dev/my_project/node_modules/express/lib/response.js:267:15)
    at HttpExceptionFilter.catch (/Users/sasha/Dev/my_project/dist/@core/exception/http.exception.js:24:14)
    at ExceptionsHandler.invokeCustomFilters (/Users/sasha/Dev/my_project/node_modules/@nestjs/core/exceptions/exceptions-handler.js:31:26)
    at ExceptionsHandler.next (/Users/sasha/Dev/my_project/node_modules/@nestjs/core/exceptions/exceptions-handler.js:12:18)
    at /Users/sasha/Dev/my_project/node_modules/@nestjs/core/router/router-proxy.js:12:35
    at process._tickCallback (internal/process/next_tick.js:68:7)

It happens because:

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.

So the questions are:

  1. Is this expected behaviour for nest ?
  2. Is there any better way to handle such cases in nest ?

Most helpful comment

It's an expected behavior. The built-in filter is trying to respond to the user with res.json, but res.write has been called already. In such case, you have to catch this exception in the controller's method OR create a dedicated exception filter.

All 3 comments

It's an expected behavior. The built-in filter is trying to respond to the user with res.json, but res.write has been called already. In such case, you have to catch this exception in the controller's method OR create a dedicated exception filter.

my call back fuction call mult itime

router.get('/sql',function(req,res,next){

GetTesterData(function(err,data){ if(err) { callback(err,null);} else{
res.json({"status":200,"data":data});
}
});

function GetTesterData(callback){
db.all("SELECT * FROM assign_scan where user_id=?",14,function(err,rows){
rows.forEach((row) => {
var sid=row.scan_id;
db.all('SELECT * FROM testing_report WHERE status=? AND scan_id=?', [0,sid], (err, rows) => {
callback(err,rows); // my call back fuction call multitimes so that i will face this type of error
});
});
});
}
});

i am getting this error

rror [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
at ServerResponse.setHeader (_http_outgoing.js:470:11)
at ServerResponse.header (D:\node\test\myapp\node_modules\express\lib\response.js:767:10)
at ServerResponse.send (D:\node\test\myapp\node_modules\express\lib\response.js:170:12)
at ServerResponse.json (D:\node\test\myapp\node_modules\express\lib\response.js:267:15)
at D:\node\test\myapp\routes\index.js:39:11
at Statement.db.all (D:\node\test\myapp\routes\index.js:51:16)
--> in Database#all('SELECT * FROM testing_report WHERE status=? AND scan_id=?', [ 0, 1 ], [Function])
at rows.forEach (D:\node\test\myapp\routes\index.js:50:18)
at Array.forEach ()
at Statement. (D:\node\test\myapp\routes\index.js:48:14)

how it solve

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

JulianBiermann picture JulianBiermann  路  3Comments

2233322 picture 2233322  路  3Comments

rlesniak picture rlesniak  路  3Comments

hackboy picture hackboy  路  3Comments

artaommahe picture artaommahe  路  3Comments