Handling Mongoose validation errors – where and how?

At this point it seems logical to buy in to how mongoose handles errors.

You would not want your models to handle error messages. The presentation layer (controllers?) should rely on the type to decide on which is the best user-friendly message to display (i18n considered).

There’s also the case where validation may happen by using a middleware. In this case, the error message that will surface up to your controller is whatever you pass to the next() callback.

So, for the case of middleware, although not documented, in order to keep a consistent validation API across your models you should directly use Mongoose’s Error constructors:

var mongoose = require('mongoose');
var ValidationError = mongoose.Error.ValidationError;
var ValidatorError  = mongoose.Error.ValidatorError;

schema.pre('save', function (next) {
  if (/someregex/i.test(this.email)) {
    var error = new ValidationError(this);
    error.errors.email = new ValidatorError('email', 'Email is not valid', 'notvalid', this.email);
    return next(error);
  }

  next();
});

That way you are guaranteed a consistent validation error handling even if the validation error originates from a middleware.

To properly match error messages to types I’d create an enum which would act as a static map for all possible types:

// my controller.js

var ValidationErrors = {
  REQUIRED: 'required',
  NOTVALID: 'notvalid',
  /* ... */
};


app.post('/register', function(req, res){
  var user = new userModel.Model(req.body);

  user.save(function(err){
    if (err) {
      var errMessage="";

      // go through all the errors...
      for (var errName in err.errors) {
        switch(err.errors[errName].type) {
          case ValidationErrors.REQUIRED:
            errMessage = i18n('Field is required');
            break;
          case ValidationErrors.NOTVALID:
            errMessage = i18n('Field is not valid');
            break;
        }
      }
      res.send(errMessage);

    }
  });
});

Leave a Comment

Hata!: SQLSTATE[HY000] [1045] Access denied for user 'divattrend_liink'@'localhost' (using password: YES)