diff --git a/lib/model.js b/lib/model.js index 65e0211e715..9980b53d967 100644 --- a/lib/model.js +++ b/lib/model.js @@ -2812,19 +2812,27 @@ Model.create = async function create(doc, options) { } else { const last = arguments[arguments.length - 1]; options = {}; - if (typeof last === 'function' || (arguments.length > 1 && !last)) { - if (typeof options === 'function' || - typeof arguments[2] === 'function') { - throw new MongooseError('Model.create() no longer accepts a callback'); - } + const hasCallback = typeof last === 'function' || + typeof options === 'function' || + typeof arguments[2] === 'function'; + if (hasCallback) { + throw new MongooseError('Model.create() no longer accepts a callback'); } else { args = [...arguments]; + // For backwards compatibility with 6.x, because of gh-5061 Mongoose 6.x and + // older would treat a falsy last arg as a callback. We don't want to throw + // an error here, because it would look strange if `Test.create({}, void 0)` + // threw a callback error. But we also don't want to create an unnecessary document. + if (args.length > 1 && !last) { + args.pop(); + } } if (args.length === 2 && args[0] != null && args[1] != null && args[0].session == null && + last && getConstructorName(last.session) === 'ClientSession' && !this.schema.path('session')) { // Probably means the user is running into the common mistake of trying diff --git a/test/model.create.test.js b/test/model.create.test.js index 646b76c01f5..4bbad5ba336 100644 --- a/test/model.create.test.js +++ b/test/model.create.test.js @@ -166,6 +166,14 @@ describe('model', function() { assert.ok(doc._id); }); }); + + it('ignores undefined last arg (gh-13487)', async function() { + await B.deleteMany({}); + await B.create({ title: 'foo' }, void 0); + const docs = await B.find(); + assert.equal(docs.length, 1); + assert.equal(docs[0].title, 'foo'); + }); }); }); });