#7037·mongoose

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.

  1. The model: model/section.js
javascript
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);
  1. The service: service/section.js
javascript
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();
    }
}
  1. Try to save a document:
javascript
SectionService.save({name: 'name', custom: 'custom'});
  1. Then the document it's saved without the custom field.

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