Skip to content

Commit

Permalink
fix(update): set CastError path to full path if casting update fails
Browse files Browse the repository at this point in the history
Fix #14114
  • Loading branch information
vkarpov15 committed Dec 7, 2023
1 parent c97d91c commit 86df50c
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 7 deletions.
9 changes: 8 additions & 1 deletion lib/schema/bigint.js
Expand Up @@ -212,7 +212,14 @@ SchemaBigInt.prototype.castForQuery = function($conditional, val, context) {
return this.applySetters(null, val, context);
}

return this.applySetters(val, context);
try {
return this.applySetters(val, context);
} catch (err) {
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
err.path = this.$fullPath;
}
throw err;
}
};

/**
Expand Down
9 changes: 8 additions & 1 deletion lib/schema/boolean.js
Expand Up @@ -256,7 +256,14 @@ SchemaBoolean.prototype.castForQuery = function($conditional, val, context) {
return this.applySetters(null, val, context);
}

return this.applySetters(val, context);
try {
return this.applySetters(val, context);
} catch (err) {
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
err.path = this.$fullPath;
}
throw err;
}
};

/**
Expand Down
11 changes: 10 additions & 1 deletion lib/schema/buffer.js
Expand Up @@ -279,7 +279,16 @@ SchemaBuffer.prototype.castForQuery = function($conditional, val, context) {
}
return handler.call(this, val);
}
const casted = this.applySetters(val, context);

let casted;
try {
casted = this.applySetters(val, context);
} catch (err) {
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
err.path = this.$fullPath;
}
throw err;
}
return casted ? casted.toObject({ transform: false, virtuals: false }) : casted;
};

Expand Down
9 changes: 8 additions & 1 deletion lib/schema/date.js
Expand Up @@ -407,7 +407,14 @@ SchemaDate.prototype.$conditionalHandlers = {

SchemaDate.prototype.castForQuery = function($conditional, val, context) {
if ($conditional == null) {
return this.applySetters(val, context);
try {
return this.applySetters(val, context);
} catch (err) {
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
err.path = this.$fullPath;
}
throw err;
}
}

const handler = this.$conditionalHandlers[$conditional];
Expand Down
11 changes: 10 additions & 1 deletion lib/schema/number.js
Expand Up @@ -429,7 +429,16 @@ SchemaNumber.prototype.castForQuery = function($conditional, val, context) {
}
return handler.call(this, val, context);
}
val = this.applySetters(val, context);

try {
val = this.applySetters(val, context);
} catch (err) {
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
err.path = this.$fullPath;
}
throw err;
}

return val;
};

Expand Down
9 changes: 8 additions & 1 deletion lib/schema/string.js
Expand Up @@ -688,7 +688,14 @@ SchemaString.prototype.castForQuery = function($conditional, val, context) {
return val;
}

return this.applySetters(val, context);
try {
return this.applySetters(val, context);
} catch (err) {
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
err.path = this.$fullPath;
}
throw err;
}
};

/*!
Expand Down
9 changes: 8 additions & 1 deletion lib/schemaType.js
Expand Up @@ -1630,7 +1630,14 @@ SchemaType.prototype.castForQuery = function($conditional, val, context) {
return handler.call(this, val, context);
}

return this.applySetters(val, context);
try {
return this.applySetters(val, context);
} catch (err) {
if (err instanceof CastError && err.path === this.path && this.$fullPath != null) {
err.path = this.$fullPath;
}
throw err;
}
};

/**
Expand Down
30 changes: 30 additions & 0 deletions test/model.findOneAndUpdate.test.js
Expand Up @@ -2200,4 +2200,34 @@ describe('model: findOneAndUpdate:', function() {
);
assert.equal(updated.defaultField, 'some non-default value');
});

it('sets CastError path to full path (gh-14114)', async function() {
const testSchema = new mongoose.Schema({
id: mongoose.Schema.Types.ObjectId,
name: String,
accessories: [
{
isEnabled: Boolean,
additionals: [
{
k: String,
v: Number
}
]
}
]
});
const Test = db.model('Test', testSchema);
const err = await Test.findOneAndUpdate(
{},
{
$set: {
'accessories.0.additionals.0.k': ['test']
}
}
).then(() => null, err => err);
assert.ok(err);
assert.equal(err.name, 'CastError');
assert.equal(err.path, 'accessories.0.additionals.0.k');
});
});

0 comments on commit 86df50c

Please sign in to comment.