{"record":{"id":"1e4caabc6322c1df","repo":"Automattic/mongoose","slug":"model-insertmany-no-longer-accepts-a-callback","errorCode":null,"errorMessage":"Model.insertMany() no longer accepts a callback","messagePattern":"Model\\.insertMany\\(\\) no longer accepts a callback","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/model.js","lineNumber":3032,"sourceCode":" * @param {object} [options] see the [mongodb driver options](https://mongodb.github.io/node-mongodb-native/7.0/classes/Collection.html#insertMany)\n * @param {boolean} [options.ordered=true] if true, will fail fast on the first error encountered. If false, will insert all the documents it can and report errors later. An `insertMany()` with `ordered = false` is called an \"unordered\" `insertMany()`.\n * @param {boolean} [options.rawResult=false] if false, the returned promise resolves to the documents that passed mongoose document validation. If `true`, will return the [raw result from the MongoDB driver](https://mongodb.github.io/node-mongodb-native/7.0/interfaces/InsertManyResult.html) with a `mongoose` property that contains `validationErrors` and `results` if this is an unordered `insertMany`.\n * @param {boolean} [options.lean=false] if `true`, skips hydrating the documents. This means Mongoose will **not** cast, validate, or apply defaults to any of the documents passed to `insertMany()`. This option is useful if you need the extra performance, but comes with data integrity risk. Consider using with [`castObject()`](https://mongoosejs.com/docs/api/model.html#Model.castObject()) and [`applyDefaults()`](https://mongoosejs.com/docs/api/model.html#Model.applyDefaults()).\n * @param {number} [options.limit=null] this limits the number of documents being processed (validation/casting) by mongoose in parallel, this does **NOT** send the documents in batches to MongoDB. Use this option if you're processing a large number of documents and your app is running out of memory.\n * @param {string|object|Array} [options.populate=null] populates the result documents. This option is a no-op if `rawResult` is set.\n * @param {boolean} [options.throwOnValidationError=false] If true and `ordered: false`, throw an error if one of the operations failed validation, but all valid operations completed successfully.\n * @param {boolean|object} [options.middleware=true] set to `false` to skip all user-defined middleware\n * @param {boolean} [options.middleware.pre=true] set to `false` to skip only pre hooks\n * @param {boolean} [options.middleware.post=true] set to `false` to skip only post hooks\n * @return {Promise} resolving to the raw result from the MongoDB driver if `options.rawResult` was `true`, or the documents that passed validation, otherwise\n * @api public\n */\n\nModel.insertMany = async function insertMany(arr, options) {\n  _checkContext(this, 'insertMany');\n  if (typeof options === 'function' ||\n    typeof arguments[2] === 'function') {\n    throw new MongooseError('Model.insertMany() no longer accepts a callback');\n  }\n\n  const ThisModel = this;\n  return traceInsertMany(function maybeTracedInsertMany() { return _insertMany.call(ThisModel, arr, options); }, () => ({\n    operation: 'insertMany',\n    collection: ThisModel.collection.name,\n    database: ThisModel.db?.name,\n    serverAddress: ThisModel.db?.host,\n    serverPort: ThisModel.db?.port,\n    args: { docs: arr, options }\n  }));\n};\n\nasync function _insertMany(arr, options) {\n  options = options || {};\n  const hasInsertManyHooks = this._middleware.hasHooks('insertMany');\n  const preFilter = hasInsertManyHooks ? buildMiddlewareFilter(options, 'pre') : null;\n  const postFilter = hasInsertManyHooks ? buildMiddlewareFilter(options, 'post') : null;","sourceCodeStart":3014,"sourceCodeEnd":3050,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/model.js#L3014-L3050","documentation":"Model.insertMany() is async and promise-only in Mongoose 7+; the guard throws (as a rejected promise) when options is a function or a third argument is a function, covering both legacy forms insertMany(docs, callback) and insertMany(docs, options, callback).","triggerScenarios":"Model.insertMany(docs, cb) with the callback in the options slot, or Model.insertMany(docs, { ordered: false }, cb) with the callback as the third argument.","commonSituations":"Seed scripts and bulk-import jobs written for Mongoose 6; upgrading a codebase where only the insertMany call sites were missed; older libraries wrapping insertMany with callbacks.","solutions":["Use await: const docs = await Model.insertMany(docs, { ordered: false }); inside try/catch","Or .then()/.catch() on the returned promise","Sweep for callback patterns on all bulk methods (insertMany, bulkWrite, create) during the Mongoose 7 migration","Pin mongoose@6 temporarily if the rewrite must be deferred","Use TypeScript so callback overloads fail to compile"],"exampleFix":"// before\nUser.insertMany(users, (err, docs) => { ... });\n\n// after\nconst docs = await User.insertMany(users);","handlingStrategy":"validation","validationCode":"function insertManySafe(Model, docs, options) {\n  if (typeof options === 'function') throw new TypeError('insertMany: use await, not a callback');\n  if (arguments.length > 3) throw new TypeError('insertMany: too many arguments');\n  return Model.insertMany(docs, options);\n}","typeGuard":null,"tryCatchPattern":"try {\n  const saved = await Model.insertMany(docs, { ordered: false });\n} catch (err) {\n  if (/no longer accepts a callback/.test(err.message)) { /* migrate call site to await */ }\n  else throw err;\n}","preventionTips":["Include insertMany and bulkWrite in the same Mongoose 7 migration pass as create()","Use TypeScript: promise-only signatures catch callback forms at compile time","Wrap bulk operations in one promise-based repository method instead of scattering call styles"],"tags":["mongoose","callback","promise","migration","insertmany","bulk"],"backgroundTag":"callback-to-promise-migration","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}