1

I'm using Node and MongoDB to create a team grouping and have run into a node console error:

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 2): TypeError: Cannot read property 'apply' of undefined

I'm using Axios to post a request to an my Node JS API that should create a new entry in my MongoDB. Here is my code:

Controller:

const mongoose = require('mongoose');
const Team = mongoose.model('Team');
const promisify = require('es6-promisify');


exports.validateTeamName = (req,res,next) => { 

    req.sanitizeBody('teamName');
    req.checkBody('teamName','You must supply a name!').notEmpty();  
    req.sanitizeBody('userId');
    req.checkBody('userId','There was an error with your user id - please log out and log back in!').notEmpty();  
    const errors = req.validationErrors();
    if(errors) {
        req.flash('error',errors.map(err => err.msg));
        res.json(req.flash())
        return; //if theres errors stop the function from running
    }
    next();
};

exports.register = async (req,res,next) => {

    const team = new Team({
                teamName:req.body.teamName,
                owner:req.body.userId
    })

    const register = promisify(Team.register,Team);
    await register(team,req.body.password);

        next()

}

exports.finishCreateTeam = async (req,res,next) => {
    console.log('all done')
}

Model:

const mongoose = require('mongoose');
const Schema = mongoose.Schema;
mongoose.Promise = global.Promise;
const md5 = require('md5');
const validator = require('validator');
const mongodbErrorHandler = require('mongoose-mongodb-errors');
const passportLocalMongoose = require('passport-local-mongoose');

const teamSchema = new Schema({
    teamName:{
        type:String,    
        trim:true,     
        required:'Please supply a team name'        
    },
        owner:{
        type:String,    
        trim:false,   
                required:'Please supply a user ID'    
        }
});

teamSchema.plugin(mongodbErrorHandler);

module.exports = mongoose.model('Team',teamSchema);

Route:

router.post('/createteam',
    manageTeamController.validateTeamName,
    manageTeamController.register,
        manageTeamController.finishCreateTeam
);

I used very similar functionality to create users so i'm not sure where i've gone wrong here, plus i'm not entirely sure what the error means.. When I comment out the await register(team,req.body.password); the error goes away so I guess this is where i've gone wrong but not sure how!

Here is the stack trace i'm getting after adding in the unhandledRejection log that was suggested:

[] Promise {
[]   <rejected> TypeError: Cannot read property 'apply' of undefined
[]     at C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\es6-promisify\dist\promisify.js:75:40
[]     at Promise (<anonymous>)
[]     at C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\es6-promisify\dist\promisify.js:54:20
[]     at exports.register (C:\Users\BenLi\Desktop\development projects\note app\new\server\controllers\manageTeamController.js:29:11)
[]     at Layer.handle [as handle_request] (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\layer.js:95:5)
[]     at next (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\route.js:137:13)
[]     at exports.validateTeamName (C:\Users\BenLi\Desktop\development projects\note app\new\server\controllers\manageTeamController.js:18:5)
[]     at Layer.handle [as handle_request] (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\layer.js:95:5)
[]     at next (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\route.js:137:13)
[]     at Route.dispatch (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\route.js:112:3)
[]     at Layer.handle [as handle_request] (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\layer.js:95:5)
[]     at C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\index.js:281:22
[]     at Function.process_params (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\index.js:335:12)
[]     at next (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\index.js:275:10)
[]     at Function.handle (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\index.js:174:3)
[]     at router (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\index.js:47:12)
[]     at Layer.handle [as handle_request] (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\layer.js:95:5)
[]     at trim_prefix (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\index.js:317:13)
[]     at C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\index.js:284:7
[]     at Function.process_params (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\index.js:335:12)
[]     at next (C:\Users\BenLi\Desktop\development projects\note app\new\server\node_modules\express\lib\router\index.js:275:10)
[]     at app.use (C:\Users\BenLi\Desktop\development projects\note app\new\server\app.js:73:3) }

Here is line 73 in app.js:

app.use((req, res, next) => {
  req.login = promisify(req.login, req);
  next();
});
red house 87
  • 1,837
  • 9
  • 50
  • 99
  • yes the problem is in registration. Block the await with try catch to see the error – Vasileios Pallas Oct 10 '17 at 13:41
  • 1
    Possible duplicate of [how to find which promises is unhandled in nodejs UnhandledPromiseRejectionWarning?](https://stackoverflow.com/questions/43834559/how-to-find-which-promises-is-unhandled-in-nodejs-unhandledpromiserejectionwarni) – ponury-kostek Oct 10 '17 at 13:44

2 Answers2

2

Enable Promise rejection logging, so you can see the line number of the error:

// Show unhandled rejections
process.on('unhandledRejection', function(reason, promise) {
    console.log(promise);
});

This looks like Express, so you'd do this in app.js.

Off topic: you probably don't want to be using md5 for hashing in 2017 - it's pretty easy for someone to make two things with the same hash.

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
  • I have updated my question with the console log it gives. Looks lie the error is coming from promisify library? – red house 87 Oct 10 '17 at 13:50
  • Looks like the `app.use` on `note app\new\server\app.js:73:3` is the line that is causing the issue. – mikemaccana Oct 10 '17 at 14:17
  • @BenLiger I'd just use https://nodejs.org/api/util.html#util_util_promisify_original which takes a single argument. Also you're just making req.login a function that returns a promise on each time the route is started. That seems odd - what are you trying to do? – mikemaccana Oct 11 '17 at 13:22
0

I'm guessing that Team.register is undefined, which can't be called as a function.

When the promisified register method is called, it doesn't have a reference to the method. It's trying to call undefined.apply(scope, args), which throws the error

TypeError: Cannot read property 'apply' of undefined

Looking through the mongoose docs, I don't see model.register anywhere. Check the docs for the appropriate method.

posit labs
  • 8,951
  • 4
  • 36
  • 66