Skip to content

Commit cdedde6

Browse files
authored
Merge pull request #14587 from Automattic/vkarpov15/gh-14572
fix(model): make `bulkWrite()` and `insertMany()` throw if `throwOnValidationError` set and all ops invalid
2 parents 40805aa + 55d9d7e commit cdedde6

File tree

2 files changed

+57
-3
lines changed

2 files changed

+57
-3
lines changed

lib/model.js

+16
Original file line numberDiff line numberDiff line change
@@ -3233,6 +3233,14 @@ Model.$__insertMany = function(arr, options, callback) {
32333233

32343234
// Quickly escape while there aren't any valid docAttributes
32353235
if (docAttributes.length === 0) {
3236+
if (throwOnValidationError) {
3237+
return callback(new MongooseBulkWriteError(
3238+
validationErrors,
3239+
results,
3240+
null,
3241+
'insertMany'
3242+
));
3243+
}
32363244
if (rawResult) {
32373245
const res = {
32383246
acknowledged: true,
@@ -3588,6 +3596,14 @@ Model.bulkWrite = async function bulkWrite(ops, options) {
35883596
validOps = validOps.sort().map(index => ops[index]);
35893597

35903598
if (validOps.length === 0) {
3599+
if (options.throwOnValidationError && validationErrors.length) {
3600+
throw new MongooseBulkWriteError(
3601+
validationErrors,
3602+
results,
3603+
res,
3604+
'bulkWrite'
3605+
);
3606+
}
35913607
return getDefaultBulkwriteResult();
35923608
}
35933609

test/model.test.js

+41-3
Original file line numberDiff line numberDiff line change
@@ -4062,7 +4062,32 @@ describe('Model', function() {
40624062
assert.ok(doc.createdAt.valueOf() >= now.valueOf());
40634063
assert.ok(doc.updatedAt);
40644064
assert.ok(doc.updatedAt.valueOf() >= now.valueOf());
4065+
});
4066+
4067+
it('throwOnValidationError (gh-14572)', async function() {
4068+
const schema = new Schema({
4069+
num: Number
4070+
});
4071+
4072+
const M = db.model('Test', schema);
4073+
4074+
const ops = [
4075+
{
4076+
insertOne: {
4077+
document: {
4078+
num: 'not a number'
4079+
}
4080+
}
4081+
}
4082+
];
40654083

4084+
const err = await M.bulkWrite(
4085+
ops,
4086+
{ ordered: false, throwOnValidationError: true }
4087+
).then(() => null, err => err);
4088+
assert.ok(err);
4089+
assert.equal(err.name, 'MongooseBulkWriteError');
4090+
assert.equal(err.validationErrors[0].errors['num'].name, 'CastError');
40664091
});
40674092

40684093
it('with child timestamps and array filters (gh-7032)', async function() {
@@ -6602,14 +6627,14 @@ describe('Model', function() {
66026627
});
66036628

66046629
it('insertMany should throw an error if there were operations that failed validation, ' +
6605-
'but all operations that passed validation succeeded (gh-13256)', async function() {
6630+
'but all operations that passed validation succeeded (gh-14572) (gh-13256)', async function() {
66066631
const userSchema = new Schema({
66076632
age: { type: Number }
66086633
});
66096634

66106635
const User = db.model('User', userSchema);
66116636

6612-
const err = await User.insertMany([
6637+
let err = await User.insertMany([
66136638
new User({ age: 12 }),
66146639
new User({ age: 12 }),
66156640
new User({ age: 'NaN' })
@@ -6623,7 +6648,20 @@ describe('Model', function() {
66236648
assert.ok(err.results[2] instanceof Error);
66246649
assert.equal(err.results[2].errors['age'].name, 'CastError');
66256650

6626-
const docs = await User.find();
6651+
let docs = await User.find();
6652+
assert.deepStrictEqual(docs.map(doc => doc.age), [12, 12]);
6653+
6654+
err = await User.insertMany([
6655+
new User({ age: 'NaN' })
6656+
], { ordered: false, throwOnValidationError: true })
6657+
.then(() => null)
6658+
.catch(err => err);
6659+
6660+
assert.ok(err);
6661+
assert.equal(err.name, 'MongooseBulkWriteError');
6662+
assert.equal(err.validationErrors[0].errors['age'].name, 'CastError');
6663+
6664+
docs = await User.find();
66276665
assert.deepStrictEqual(docs.map(doc => doc.age), [12, 12]);
66286666
});
66296667

0 commit comments

Comments
 (0)