how to recover from duplicate key in mongoose + express
11,115
Solution 1
I have not tried this yet, but this is what I'm thinking will avoid causing an error:
//look for existing user first
user.findOne({ username: req.body.username }, function(err, user) {
if ( err ) throw err;
//existing user found, stop registration
if ( user ) {
res.flash('error', "That user already exists");
res.redirect('/signup');
return;
}
//create new user
var user = new User({ username: req.body.username });
user.save(function(err){
if ( err ) throw err;
res.flash('info', "Your account has been created");
res.redirect('/account');
});
});
Solution 2
Try this:
user.save(function(err){
if ( err && err.code !== 11000 ) {
console.log(err);
console.log(err.code);
res.send('Another error showed up');
return;
}
//duplicate key
if ( err && err.code === 11000 ) {
req.flash('error', 'User already exists');
res.redirect('/signup');
return;
}
res.locals.user = user;
req.session.user = user;
//res.locals.session = req.session;
res.redirect('/');
});
You won't fill the error log this way.
Related videos on Youtube
Comments
-
chovy over 1 year
I've created a signup form using mongoose and express 3
Its possible the user already exists with that username, in which case I get an err.code 11000 (duplicate key). How should I handle existing users?
This is what I'm doing now....but I'm not sure checking error code is best way:
user.save(function(err){ if ( err ) { console.log(err); console.log(err.code); //duplicate key if ( err.code == 11000 ) { req.flash('error', 'User already exists'); res.redirect('/signup'); return; } } res.locals.user = user; req.session.user = user; //res.locals.session = req.session; res.redirect('/'); });
Is there a better way of doing this?
-
chovy over 11 yearsisn't that what I had? What's hte difference. and errors do show up in log regardless...not sure how this is any different.
-
red over 11 yearsSorry @chovy, modified my answer a bit. - First conditional will happen in case the error is not a "duplicate key" error and return 'Another error showed up' to the client. - Second conditional will happen in case the error is a "duplicate key" error. - If no error, the script will go as instructed.
-
chovy over 11 yearsI see -- thanks. I still think errors are logged though, since the query threw an error. I might do user.findOne(.., function(err, user) { if ( !user ) new User(); user.save() });
-
Matt Fletcher over 9 yearsYou can also use
.count()
which is slightly more succinct/memorable but doesn't allow for using the returned data if required. -
Matt Fletcher over 9 yearsPs, I do think that mongoose should have something like
Model.saveUnique({username: req.body.username}, function (err) { ... });
-
binki almost 7 yearsIt is actually safer to handle the duplicate key error because it is possible for another request to have created the user between when
user.findOne()
reads the collection anduser.save()
executes. I.e., there’s a race condition where your API could throw a 5xx error. For a form where you’re expecting the user not to exist already, just trying to save it and then handling an anticipated DuplicateKey error is less code (no need foruser.findOne()
) and avoids this race condition. If you expect the entity to exist already, it might be more natural to try to load it first.