Skip to content

Commit 3bd67a8

Browse files
authored
Merge pull request #14161 from Automattic/vkarpov15/gh-14114
fix(update): set CastError path to full path if casting update fails
2 parents 6d87344 + 6f7b659 commit 3bd67a8

File tree

10 files changed

+102
-10
lines changed

10 files changed

+102
-10
lines changed

lib/schema/bigint.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,14 @@ SchemaBigInt.prototype.castForQuery = function($conditional, val, context) {
212212
return this.applySetters(null, val, context);
213213
}
214214

215-
return this.applySetters(val, context);
215+
try {
216+
return this.applySetters(val, context);
217+
} catch (err) {
218+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
219+
err.path = this.$fullPath;
220+
}
221+
throw err;
222+
}
216223
};
217224

218225
/**

lib/schema/boolean.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,14 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val, context) {
256256
return this.applySetters(null, val, context);
257257
}
258258

259-
return this.applySetters(val, context);
259+
try {
260+
return this.applySetters(val, context);
261+
} catch (err) {
262+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
263+
err.path = this.$fullPath;
264+
}
265+
throw err;
266+
}
260267
};
261268

262269
/**

lib/schema/buffer.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,16 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val, context) {
279279
}
280280
return handler.call(this, val);
281281
}
282-
const casted = this.applySetters(val, context);
282+
283+
let casted;
284+
try {
285+
casted = this.applySetters(val, context);
286+
} catch (err) {
287+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
288+
err.path = this.$fullPath;
289+
}
290+
throw err;
291+
}
283292
return casted ? casted.toObject({ transform: false, virtuals: false }) : casted;
284293
};
285294

lib/schema/date.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,14 @@ SchemaDate.prototype.$conditionalHandlers = {
407407

408408
SchemaDate.prototype.castForQuery = function($conditional, val, context) {
409409
if ($conditional == null) {
410-
return this.applySetters(val, context);
410+
try {
411+
return this.applySetters(val, context);
412+
} catch (err) {
413+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
414+
err.path = this.$fullPath;
415+
}
416+
throw err;
417+
}
411418
}
412419

413420
const handler = this.$conditionalHandlers[$conditional];

lib/schema/number.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -429,7 +429,16 @@ SchemaNumber.prototype.castForQuery = function($conditional, val, context) {
429429
}
430430
return handler.call(this, val, context);
431431
}
432-
val = this.applySetters(val, context);
432+
433+
try {
434+
val = this.applySetters(val, context);
435+
} catch (err) {
436+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
437+
err.path = this.$fullPath;
438+
}
439+
throw err;
440+
}
441+
433442
return val;
434443
};
435444

lib/schema/string.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -688,7 +688,14 @@ SchemaString.prototype.castForQuery = function($conditional, val, context) {
688688
return val;
689689
}
690690

691-
return this.applySetters(val, context);
691+
try {
692+
return this.applySetters(val, context);
693+
} catch (err) {
694+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
695+
err.path = this.$fullPath;
696+
}
697+
throw err;
698+
}
692699
};
693700

694701
/*!

lib/schema/uuid.js

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,8 +344,15 @@ SchemaUUID.prototype.castForQuery = function($conditional, val, context) {
344344
if (!handler)
345345
throw new Error('Can\'t use ' + $conditional + ' with UUID.');
346346
return handler.call(this, val, context);
347-
} else {
348-
return this.cast(val);
347+
}
348+
349+
try {
350+
return this.applySetters(val, context);
351+
} catch (err) {
352+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
353+
err.path = this.$fullPath;
354+
}
355+
throw err;
349356
}
350357
};
351358

lib/schemaType.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1630,7 +1630,14 @@ SchemaType.prototype.castForQuery = function($conditional, val, context) {
16301630
return handler.call(this, val, context);
16311631
}
16321632

1633-
return this.applySetters(val, context);
1633+
try {
1634+
return this.applySetters(val, context);
1635+
} catch (err) {
1636+
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
1637+
err.path = this.$fullPath;
1638+
}
1639+
throw err;
1640+
}
16341641
};
16351642

16361643
/**

test/model.findOneAndUpdate.test.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2200,4 +2200,34 @@ describe('model: findOneAndUpdate:', function() {
22002200
);
22012201
assert.equal(updated.defaultField, 'some non-default value');
22022202
});
2203+
2204+
it('sets CastError path to full path (gh-14114)', async function() {
2205+
const testSchema = new mongoose.Schema({
2206+
id: mongoose.Schema.Types.ObjectId,
2207+
name: String,
2208+
accessories: [
2209+
{
2210+
isEnabled: Boolean,
2211+
additionals: [
2212+
{
2213+
k: String,
2214+
v: Number
2215+
}
2216+
]
2217+
}
2218+
]
2219+
});
2220+
const Test = db.model('Test', testSchema);
2221+
const err = await Test.findOneAndUpdate(
2222+
{},
2223+
{
2224+
$set: {
2225+
'accessories.0.additionals.0.k': ['test']
2226+
}
2227+
}
2228+
).then(() => null, err => err);
2229+
assert.ok(err);
2230+
assert.equal(err.name, 'CastError');
2231+
assert.equal(err.path, 'accessories.0.additionals.0.k');
2232+
});
22032233
});

test/schema.select.test.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@ describe('schema select option', function() {
1515

1616
before(function() {
1717
db = start();
18+
mongoose.set('debug', true);
1819
});
1920

2021
after(async function() {
2122
await db.close();
23+
mongoose.set('debug', false);
2224
});
2325

2426
beforeEach(() => db.deleteModel(/.*/));
@@ -53,7 +55,7 @@ describe('schema select option', function() {
5355
assert.equal(findByIdDocAgain.isSelected('name'), false);
5456
assert.equal(findByIdDocAgain.isSelected('docs.name'), false);
5557
assert.strictEqual(undefined, findByIdDocAgain.name);
56-
const findUpdateDoc = await Test.findOneAndUpdate({ _id: doc._id });
58+
const findUpdateDoc = await Test.findOneAndUpdate({ _id: doc._id }, { name: 'the excluded' });
5759
assert.equal(findUpdateDoc.isSelected('name'), false);
5860
assert.equal(findUpdateDoc.isSelected('docs.name'), false);
5961
assert.strictEqual(undefined, findUpdateDoc.name);

0 commit comments

Comments
 (0)