Mongoose unique validator does not behave like other validators - node.js

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.

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)

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);
}
});

Related

Error: Value for argument "data" is not a valid Firestore document. Cannot use "undefined" as a Firestore value (found in field "chatId")

I've been implementing in my website backend a notification system when a new message is created, the database is structured like in this image:
But when the messages is created this error occured:
Error
Error: Value for argument "data" is not a valid Firestore document. Cannot use "undefined" as a Firestore value (found in field "chatId"). If you want to ignore undefined values, enable `ignoreUndefinedProperties`.
at validateUserInput (/workspace/node_modules/#google-cloud/firestore/build/src/serializer.js:271:19)
at Object.validateUserInput (/workspace/node_modules/#google-cloud/firestore/build/src/serializer.js:263:13)
at validateDocumentData (/workspace/node_modules/#google-cloud/firestore/build/src/write-batch.js:590:18)
at WriteBatch.set (/workspace/node_modules/#google-cloud/firestore/build/src/write-batch.js:256:9)
at DocumentReference.set (/workspace/node_modules/#google-cloud/firestore/build/src/reference.js:342:14)
at /workspace/index.js:200:68
at processTicksAndRejections (internal/process/task_queues.js:97:5)
Index.js
exports.createNotificationOnFirstMessage=functions.region('europe-west1').firestore.document('/chats/{chatId}/messages/{messageId}')
.onCreate((snapshot)=>{
var recipientArrn = snapshot.data().chatId.split('_');
// recipientArrn is an array of substring, the first is the sender (index 0), the second is the recipient (index 1)
return db.doc(`/users/${recipientArrn[1]}`).get()
.then(doc =>{
if(doc.exists){
return db.doc(`/notifications/${snapshot.id}`).set({
createdAt: new Date().toISOString(),
recipient: recipientArrn[1],
sender: snapshot.data().sender,
type:'message',
read: false,
chatId: doc.chatId,
});
}
})
.catch(err =>{
console.error(err);
});
})
What can I do to resolve this error?
Ad the error message says, you are passing undefined in the value of:
chatId: doc.chatId,
So doc.chatId is undefined, which is not an allowed value for a field in Firestore.
You're probably looking for:
chatId: doc.data().chatId,

Display specific error message of Validation Error message with node js

How to display a specific error message from a Validation Error. I already display the error with this line of code return res.render("register", {error: err.message});
and show this error ValidationError: User validation failed: email: Email already exists
But it is showing my column field name 'email' and I don't wanna do that. Below is the whole error and I only want to display this message: 'Email already exists'
Ignore the location D: i removed my file directory
ValidationError: User validation failed: email: Email already exists
at ValidationError.inspect
errors:
{ email:
{ ValidatorError: Email already exists
at new ValidatorError (D:)
at validate (D:)
at D:
at process._tickCallback (internal/process/next_tick.js:68:7)
message: 'Email already exists',
name: 'ValidatorError',
properties: [Object],
kind: 'user defined',
path: 'email',
value: 'email#gmail.com',
reason: undefined,
[Symbol(mongoose:validatorError)]: true } },
_message: 'User validation failed',
name: 'ValidationError' }
To get a specific error message of Validation Error you can use mapped() function like below.
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log(errors.mapped().email.msg);
}
To access nested error message do this
err.errors.email.message
Simply create one temp variable and structure your message,
let err_msg = err.errors.email.message;
which will give: 'Email already exists'
You can leave user validation failed message, since same message may be repeated for all validations.

User validation failed: email: Invalid Email, Custom Error Needed

I am using validator npm package to validate if email is correct.
All that i need is to send a custom message - Invalid Email
but I am getting this -
User validation failed: email: Invalid Email
const UserSchema = mongoose.Schema({
email:{
type: String,
unique: true,
required: true,
trim: true,
lowercase: true,
validate: [isEmail, 'Invalid Email']
},
});
All is good but when i am catching that error and logging it -
user.save().then(data => {
res.status(201).send(data);
}).catch(err => {
console.log(err.message); // this line here logs out the error message
return res.status(500).send({
message: err.message
});
})
I need this - Invalid Error instead of User validation failed: email: Invalid Email
Thanks in advance!
You have 2 solutions here:
1. Edit the validator package and remove the 'User validation failed' line totally.
2. Split the error message:
var errMessageArray = err.message.split(':');
var messageToReturn = errMessageArray[errMessageArray.length - 1]

ValidationError: ObjectId not getting pushed into the array.. Resulting a ValidationError

I'm new to backend web development, learning Data Associations at the moment... I got an error which seems severe to me since I'm a newbie in this topic...I'm trying to add up the ObjectId of Post in postArray of my userSchema.
When I add the first post to a particular user, I'm not getting what I expected.. I was expecting to get the ObjectId pushed into the postArray but the actual thing happened here was the entire newPost got pushed into the postArray.This is the first problem encountered. And I get no errors here, but I didn't get what I expected!
The second one is when I add another post to postArray, It gives me a huge error naming ValidationError.. I literally spent hours trying to fix this error which may be a minor one but a pain for me. My code is given below and the error is also posted below!
var mongoose = require("mongoose");
mongoose.connect("mongodb://localhost/testdatabase");
var postSchema = new mongoose.Schema({
title: String,
content: String
});
var Post = mongoose.model("Post", postSchema);
var userSchema = new mongoose.Schema({
name: String,
email: String,
postArray: [{
type: mongoose.Schema.Types.ObjectId,
ref: 'Post'
}]
});
var User = mongoose.model("User", userSchema);
var alex = new User({
name: "Alexander",
email: "alexander#gmail.com"
});
alex.save();
Post.create({
title: "I'm terribly stuck here!",
content: "Does anyone have an idea of where I'm stuck?"
}, function(err, newPost) {
User.findOne({name: "Alexander"}, function(err, foundUser) {
if(err) {
console.log(err);
} else {
console.log("THE NEWLY ADDED POST IS" + newPost);
foundUser.postArray.push(newPost);
foundUser.save(function(err, savedData) {
if(err) {
console.log(err);
} else {
console.log(savedData);
}
});
}
});
});
Blackdeath:~/environment/Associations $ node references.js
THE NEWLY ADDED POST IS{ _id: 5a5845c180a490137330bcae,
title: 'I\'m terribly stuck here!',
content: 'Does anyone have an idea of where I\'m stuck?',
__v: 0 }
{ ValidationError: User validation failed: postArray: Cast to [undefined] failed for value "[{"_id":"5a5844112d4c6512beb16846","title":"This makes me sick!","content":"I\'m stuck here..Someone save me!","__v":0}]" at path "postArray"
at MongooseError.ValidationError (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/error/validation.js:27:11)
at model.Document.invalidate (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/document.js:1643:32)
at _init (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/document.js:413:18)
at init (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/document.js:381:5)
at model.Document.$__init (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/document.js:351:3)
at model.syncWrapper [as $__init] (/home/ec2-user/environment/Associations/node_modules/kareem/index.js:234:23)
at model.Document.init (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/document.js:319:8)
at completeOne (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/query.js:1980:12)
at Immediate.<anonymous> (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/query.js:1502:11)
at Immediate.<anonymous> (/home/ec2-user/environment/Associations/node_modules/mquery/lib/utils.js:119:16)
at runCallback (timers.js:672:20)
at tryOnImmediate (timers.js:645:5)
at processImmediate [as _immediateCallback] (timers.js:617:5)
errors:
{ postArray:
{ ValidatorError: Cast to [undefined] failed for value "[{"_id":"5a5844112d4c6512beb16846","title":"This makes me sick!","content":"I\'m stuck here..Someone save me!","__v":0}]" at path "postArray"
at MongooseError.ValidatorError (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/error/validator.js:25:11)
at _init (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/document.js:413:37)
at init (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/document.js:381:5)
at model.Document.$__init (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/document.js:351:3)
at model.syncWrapper [as $__init] (/home/ec2-user/environment/Associations/node_modules/kareem/index.js:234:23)
at model.Document.init (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/document.js:319:8)
at completeOne (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/query.js:1980:12)
at Immediate.<anonymous> (/home/ec2-user/environment/Associations/node_modules/mongoose/lib/query.js:1502:11)
at Immediate.<anonymous> (/home/ec2-user/environment/Associations/node_modules/mquery/lib/utils.js:119:16)
at runCallback (timers.js:672:20)
at tryOnImmediate (timers.js:645:5)
at processImmediate [as _immediateCallback] (timers.js:617:5)
message: 'Cast to [undefined] failed for value "[{"_id":"5a5844112d4c6512beb16846","title":"This makes me sick!","content":"I\\\'m stuck here..Someone save me!","__v":0}]" at path "postArray"',
name: 'ValidatorError',
properties: [Object],
kind: 'cast',
path: 'postArray',
value: '[{"_id":"5a5844112d4c6512beb16846","title":"This makes me sick!","content":"I\'m stuck here..Someone save me!","__v":0}]',
reason: undefined } },
_message: 'User validation failed',
name: 'ValidationError' }
Found the error.. I failed adding the mongoose package to package.json
At first,I just did
npm install mongoose
Later I tried doing
npm install mongoose --save
And it worked!Thank You!

Sequelize throwing 'id must be unique' on create

new to Sequelize library. From my understanding, 'id' is created automatically by sequelize (and thats what I see in the database). However when I go to 'create' an object it will throw this error:
{ [SequelizeUniqueConstraintError: Validation error]
name: 'SequelizeUniqueConstraintError',
message: 'Validation error',
errors:
[ { message: 'id must be unique',
type: 'unique violation',
path: 'id',
value: '1' } ],
fields: { id: '1' } }
The offending code:
db.Account.create({
email: req.body.email,
password: req.body.password,
allowEmail: req.body.allowEmail,
provider: 'local',
role: 'user'
})
Notice ID is not specified anywhere, neither is it specified in my model definition. Also the query it generates runs fine if I run it in postgres admin:
INSERT INTO "Accounts" ("id","email","role","verifyCode","provider","cheaterScore","isBanned","allowEmail","updatedAt","createdAt") VALUES (DEFAULT,'cat69232#gmail.com','user','','local',0,false,false,'2016-01-27 04:31:54.350 +00:00','2016-01-27 04:31:54.350 +00:00') RETURNING *;
Any ideas to what I could be missing here?
edit:
postgres version: 9.5
stack trace starts here:
/node_modules/sequelize/lib/dialects/postgres/query.js:326
Postgres has a habit of not resetting the next number in the sequence (autoincrement field) after bulk inserts. So if you're doing any pre-filling of the data in an init routine or from a SQL dump file, that's probably your issue.
Check out this post https://dba.stackexchange.com/questions/65662/postgres-how-to-insert-row-with-autoincrement-id

Resources