Make update validators fail if `upsert` is set and `required` path isn't in `$set` or `$setOnInsert`
Author: NormanPerrinCreated Sep 21, 2018Updated Jun 10, 2026
Labelsenhancementdiscussion
Do you want to request a feature or report a bug? Bug
What is the current behavior?
findOneAndUpdate doesn't run the required validations, neither with the third parameter of the method or with the pre hook.
If the current behavior is a bug, please provide the steps to reproduce.
- The model:
model/section.js
const Section = new Schema({
_id: {type: String},
name: {type: String, required: true, unique: true},
title: {type: String, required: true, unique: true}
}, {collection: 'sections', timestamps: true});
Section.pre('findOneAndUpdate', function (next) {
// workaround that works..
// const {title, name} = this.getUpdate();
// if (!isString(name)) {
// throw new Error('cannot save a Section with undefined name');
// }
// if (!isString(title)) {
// throw new Error('cannot save a Section with undefined title');
// }
this.options.upsert = true;
this.options.runValidators = true;
this.setDefaultsOnInsert = true;
next();
});
module.exports = mongoose.model('Section', Section);- The service:
service/section.js
const {Section} = require('../model');
const {isNil, isString, assign} = require('lodash');
class SectionService {
static save(section) {
if (isNil(section)) {
throw new Error('undefined Section');
}
return Section.findOneAndUpdate(
{_id: section.name},
assign(section, {_id: section.name})
).lean().exec();
}
}- Try to save a document:
SectionService.save({name: 'name', custom: 'custom'});- Then the document it's saved without the
customfield.
What is the expected behavior?
Should throw an error for being with a title field asrequired.
Please mention your node.js, mongoose and MongoDB version.
5.2.16
Source: Automattic/mongoose