Search code examples
javascriptnode.jsexpresspassport.jscradle

When I uncomment one line of code, I receive this error: _http_outgoing.js:359 throw new Error('Can\'t set headers after they are sent.');


When I uncomment this line: return done(null, false, { message: 'Incorrect username' }); in the following code, Node.js runs without any error, otherwise, Node.js gives an error mentioned later:

//we need to define a local Strategy to authenticate with username and password
passport.use(new LocalStrategy(
    function(username, password, done) { //start of custom code
        //from here starts our custom code (inside this function scope)
        //outside this scope is from passport API documentation
        //process.nextTick(function() {
        UserFind(username, function(err, user) {
                if (err) {
                    return done(err);
                } else if (!user || user.length == 0) {
                    //When I uncomment the following line of code, an error occurs, but when I comment out the following, no error is received:
                    //return done(null, false, { message: 'Incorrect username' });
                } else {
                    console.log('user._id:' + user._id);
                    console.log('typeof user: ' + typeof(user));
                    console.log('user.username: ' + user.username);
                    console.log('user.password: ' + user.password);
                    if (password !== user.password) {
                        return done(null, false, { message: 'Incorrect password' });
                    }
                    return done(null, user);
                }

            })
            //}) //process.nextTick
    } //end of custom code
));

The error received when I uncomment the above-mentioned line:

_http_outgoing.js:359 throw new Error('Can\'t set headers after they are sent.'); ^

Error: Can't set headers after they are sent. at ServerResponse.setHeader (_http_outgoing.js:359:11) at ServerResponse.header (/home/ict/Documents/hookahDB/serverjs/node_modules/express/lib/response.js:719:10) at ServerResponse.location (/home/ict/Documents/hookahDB/serverjs/node_modules/express/lib/response.js:836:15) at ServerResponse.redirect (/home/ict/Documents/hookahDB/serverjs/node_modules/express/lib/response.js:874:18) at allFailed (/home/ict/Documents/hookahDB/serverjs/node_modules/passport/lib/middleware/authenticate.js:132:20) at attempt (/home/ict/Documents/hookahDB/serverjs/node_modules/passport/lib/middleware/authenticate.js:167:28) at Strategy.strategy.fail (/home/ict/Documents/hookahDB/serverjs/node_modules/passport/lib/middleware/authenticate.js:284:9) at verified (/home/ict/Documents/hookahDB/serverjs/node_modules/passport-local/lib/strategy.js:82:30) at /home/ict/Documents/hookahDB/serverjs/index.js:158:28 at /home/ict/Documents/hookahDB/serverjs/index.js:144:16

I wonder why that single line is cause of the error and how I can resolve it. Thanks.

EDIT

Callback function is shown below:

function UserFind(username, cb) {
    db.view('users/by_username', function(err, res) {
        if (err) {
            //db.view returned error
            return cb(err);
        }
        res.forEach(function(key, value, id) {
                //1st input=key|username, 2nd input=value|userDocument, 3rd input=id|_id
                //console.log('key: '+key+' row: '+row+' id: '+ id);
                if (username === key) {
                    //found the user
                    return cb(false, value);
                }
            })
            //couldn't find the user by forEach loop
        return cb(false, false);
    })
}

Solution

  • That error message is caused by a timing error in the handling of an async response that causes you to attempt to send data on a response after the response has already been sent.

    It usually happens when people treat an async response inside an express route as a synchronous response and they end up sending data twice.

    You should add else in your statement

    if (password !== user.password) {
       return done(null, false, { message: 'Incorrect password' });
    } else {
        return done(null, user);
    }
    

    Update:

    function UserFind(username, cb) {
        var userFound = false, userVal = "";
        db.view('users/by_username', function(err, res) {
            if (err) {
                //db.view returned error
                return cb(err);
            }
            res.forEach(function(key, value, id) {
                    //1st input=key|username, 2nd input=value|userDocument, 3rd input=id|_id
                    //console.log('key: '+key+' row: '+row+' id: '+ id);
                    if (username === key) {
                        //found the user
                        userFound = true;
                        userVal = value;
                    }
                });
    
           if (userFound) {
              return cb(false, userVal);
           } else {
             // User did not found
             return cb(false, false);
           }
        })
    }