1

In my Users schema I have an email field defined as below:

...
email: {
    unique: [true, 'A user with that email address exists. The email must be unique.'],
    type: String,
    lowercase: true,
    required: [true, 'A user must have an email address']
},
...

When I leave the email empty while creating a user, I can see my cutomised error message defined in the schema required: [true, 'A user must have an email address']. However, if I pick an email address that is already used by another user, I get a different error, I cannot see my customised message defined in the unique field unique: [true, 'A user with that email address exists. The email must be unique.'].

Error when email is empty (what I find useful as getting the error message is easy): required notice that my error message A user must have an email address is shown.

Error create { MongooseError: User validation failed
at ValidationError (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/error/validation.js:23:11)
at model.Document.invalidate (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/document.js:1486:32)
at /Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/document.js:1362:17
at validate (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/schematype.js:705:7)
at /Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/schematype.js:742:9
at Array.forEach (native)
at SchemaString.SchemaType.doValidate (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/schematype.js:710:19)
at /Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/document.js:1360:9
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)
errors: 
   { email: 
      { MongooseError: A user must have an email address
      at ValidatorError (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/error/validator.js:24:11)
      at validate (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/schematype.js:704:13)
      at /Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/schematype.js:742:9
      at Array.forEach (native)
      at SchemaString.SchemaType.doValidate (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/schematype.js:710:19)
      at /Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongoose/lib/document.js:1360:9
      at _combinedTickCallback (internal/process/next_tick.js:67:7)
      at process._tickCallback (internal/process/next_tick.js:98:9)
    message: 'A user must have an email address',
    name: 'ValidatorError',
    properties: [Object],
    kind: 'required',
    path: 'email',
    value: '' } },
message: 'User validation failed',
name: 'ValidationError' }

Error when email has already been used: unique

Error create { MongoError: E11000 duplicate key error collection: stellium-io.users index: email_1 dup key: { : "john@doe.com" }
at Function.MongoError.create (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongodb-core/lib/error.js:31:11)
at toError (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongodb/lib/utils.js:114:22)
at /Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongodb/lib/collection.js:657:23
at handleCallback (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongodb/lib/utils.js:95:56)
at /Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongodb/lib/bulk/unordered.js:465:9
at handleCallback (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongodb/lib/utils.js:95:56)
at resultHandler (/Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongodb/lib/bulk/unordered.js:413:5)
at /Users/fleavamini/Projects/stellium/stellium.io/node_modules/mongodb-core/lib/connection/pool.js:455:18
at _combinedTickCallback (internal/process/next_tick.js:67:7)
at process._tickCallback (internal/process/next_tick.js:98:9)
name: 'MongoError',
message: 'E11000 duplicate key error collection: stellium-io.users index: email_1 dup key: { : "john@doe.com" }',
driver: true,
code: 11000,
index: 0,
errmsg: 'E11000 duplicate key error collection: stellium-io.users index: email_1 dup key: { : "john@doe.com" }',
getOperation: [Function],
toJSON: [Function],
toString: [Function] }

Is this the intended behaviour? I want to be able to get my customised error in the unique field and return it to the user trying to create the new user object.

borislemke
  • 8,446
  • 5
  • 41
  • 54

2 Answers2

3

Uniqueness in Mongoose is not a validation parameter(like required),it tells Mongoose to create a unique index in MongoDB for that field.

The uniqueness constraint is handled entirely in the MongoDB server. When you add a document with a duplicate key, the MongoDB server will return the error that you are showing (E11000...).

You have to handle these errors yourself if you want to create custom error messages. The Mongoose documentation (search for "Error Handling Middleware") provides you with an example on how to create custom error handling:

schmea.post('save', function(error, doc, next) {
  if (error.name === 'MongoError' && error.code === 11000) {
    next(new Error('email must be unique'));
  } else {
    next(error);
  }
});

or you can use this plugin mongoose-unique-validator

(although this doesn't provide you with the specific field for which the uniqueness constraint failed)

Manjeet Thakur
  • 2,288
  • 1
  • 16
  • 35
2

The uniqueness constraint is handled entirely in the MongoDB server. When you add a document with a duplicate key, the MongoDB server will return the error that you are showing (E11000...)

You have to handle these errors yourself if you want to create custom error messages.

like:

schmea.post('save',function(err,doc,next){
      if (err.name === 'MongoError' && err.code === 11000) {
    next(new Error('email must be unique'));
  } else {
    next(error);
  }
});
Simran
  • 2,364
  • 1
  • 12
  • 19