Automattic / Automattic/mongoose

Make update validators fail if `upsert` is set and `required` path isn't in `$set` or `$setOnInsert`

Open
#7,037 5 comments 4 reactions 0 assignees View on GitHub
discussion enhancement
Dominant language
JavaScript
Stars
27.5k
Forks
4k
Avg merge
2d 7h
Merged PRs (30d)
35

Description

**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);
```

2. 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();
}
}
```

3. Try to save a document:
```javascript
SectionService.save({name: 'name', custom: 'custom'});
```

4. 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 as`required`.

**Please mention your node.js, mongoose and MongoDB version.**
`5.2.16`

Contributor guide

Open the contributing guide

Research direction

Reproduce the behavior using model/section.js and service/section.js, focusing on findOneAndUpdate with upsert and runValidators enabled. Trace the update-validation entry point and verify that an upsert missing the required title in both $set and $setOnInsert raises a required-field error instead of saving the document.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, mongodb
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.