0

I am learning Node.js by building a simple code snippet application. It will have two field title and snippet. I am keep on getting this error as below while submitting a new snippet.

Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:535:11)
    at ServerResponse.header (/myportal/node_modules/express/lib/response.js:771:10)
    at ServerResponse.send (/myportal/node_modules/express/lib/response.js:170:12)
    at /myportal/routes/index.js:99:36
    at processTicksAndRejections (internal/process/task_queues.js:97:5) {
  code: 'ERR_HTTP_HEADERS_SENT'
}
(node:45207) UnhandledPromiseRejectionWarning: Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
    at ServerResponse.setHeader (_http_outgoing.js:535:11)
    at ServerResponse.header (/myportal/node_modules/express/lib/response.js:771:10)
    at ServerResponse.send (/myportal/node_modules/express/lib/response.js:170:12)
    at /myportal/routes/index.js:102:25
    at processTicksAndRejections (internal/process/task_queues.js:97:5)
(node:45207) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)
(node:45207) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

index.js

const express = require( "express" );
const mongoose = require( 'mongoose' );

const router = express.Router();
const snippetSchema = mongoose.model( 'snippetSchema' );

const { check, validationResult } = require( 'express-validator' );


router.post( '/newsnippet',
    [
        check( 'title' )
            .isLength( { min: 1 } )
            .withMessage( ' Please enter a valid title name.' ),
        check( 'snippet' )
            .isLength( { min: 1 } )
            .withMessage( ' Please enter a valid snippet.' ),

    ],
    ( req, res ) => {
        const errors = validationResult( req );

        if ( errors.isEmpty() ) {
            res.send( "Thank you for adding new snippet." );
            console.log( "Req Body : " + JSON.stringify( req.body ) );
            const newSnippet = new snippetSchema( req.body );
            console.log( " I am executed till creating newSnippet instantiation" + JSON.stringify( newSnippet ) );
            newSnippet.save()
                .then( () => { res.send( 'Thank you for adding new snippet :)' ); console.log( "Reached till here!" ) } )
                .catch( ( err ) => {
                    console.log( err );
                    res.send( 'Sorry! something went wrong' );

                } );
            //return;
        } else {
            res.render( 'snippets', {
                title: "My Homepage",
                errors: errors.array(),
                data: req.body,
            } );
            //return;
        }

    }

);
module.exports = router;

model code

const mongoose = require( 'mongoose' );
mongoose.set( 'useCreateIndex', true );

const snippetSchema = new mongoose.Schema( {
  title: {
    type: String,
    trim: true,
    //unique: true,
  },
  snippet_code: {
    type: String,
    trim: true,
    //unique: true,
  }

} );

module.exports = mongoose.model( 'snippetSchema', snippetSchema );

And one more observation is, even though my model has two fields such as title and snippet when initiated new model object, I am not getting my snippet field.

Debug log is as below

Req Body : {"title":"Create New Change","snippet":"var r = new Record(); var result = r.createChange({\"short_description\" :\"Sample Changee\"}); print.info(result.number);"}
 I am executed till creating newSnippet instantiation{"_id":"5ea5195c9fcbc0b10ebd7968","title":"Create New Change"}

I have searched stackoverflow and found error-cant-set-headers-after-they-are-sent-to-the-client but unable to understand.

Any suggestions, greatly appreciated.

Thank you.

Raja G
  • 5,973
  • 14
  • 49
  • 82

1 Answers1

1

You can not send response twice for the same request.

router.post( '/newsnippet',
    [
        check( 'title' )
            .isLength( { min: 1 } )
            .withMessage( ' Please enter a valid title name.' ),
        check( 'snippet' )
            .isLength( { min: 1 } )
            .withMessage( ' Please enter a valid snippet.' ),

    ],
    ( req, res ) => {
        const errors = validationResult( req );

        if ( errors.isEmpty() ) {
            const newSnippet = new snippetSchema( req.body );
            console.log( " I am executed till creating newSnippet instantiation" + JSON.stringify( newSnippet ) );
            newSnippet.save()
                .then( () => { res.send( 'Thank you for adding new snippet :)' ); console.log( "Reached till here!" ) } )
                .catch( ( err ) => {
                    console.log( err );
                    res.send( 'Sorry! something went wrong' );

                } );

Always remember, this error only happens in node when you try to set headers after response is sent.

So, look for res.send() while debugging.

These two are not the same.

router.get('/', async(req, res) => {
  return res.send('Hello world');
  res.send('Thanks for adding code snippet')!; // this line will not be executed, no errors
);

router.get('/', async(req, res) => {
  res.send('Hello world');
  res.send('Thanks for adding code snippet')!; // this line will be executed, and cause errors
);

Same is for next(). next() will cause code execution to be continued, while return next() will halt the execution and call the next middleware.

More on the topce. When you return res.send() from a middleware function, it will skip all other middlewares, and will return the response.

sujeet
  • 3,480
  • 3
  • 28
  • 60
  • Thank you and could you please help me understand how snippet is missing from new snippet record? Please refer console.log statement. – Raja G Apr 26 '20 at 07:23
  • I have removed res.send and problem solved for now. I will find some method to pass return object as success. – Raja G Apr 26 '20 at 12:05