{"record":{"id":"2f3d565540fdd408","repo":"Automattic/mongoose","slug":"querycursor-prototype-close-no-longer-accepts-a","errorCode":null,"errorMessage":"QueryCursor.prototype.close() no longer accepts a callback","messagePattern":"QueryCursor\\.prototype\\.close\\(\\) no longer accepts a callback","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/cursor/queryCursor.js","lineNumber":236,"sourceCode":"QueryCursor.prototype._markError = function(error) {\n  this._error = error;\n  return this;\n};\n\n/**\n * Marks this cursor as closed. Will stop streaming and subsequent calls to\n * `next()` will error.\n *\n * @return {Promise}\n * @api public\n * @method close\n * @emits close\n * @see AggregationCursor.close https://mongodb.github.io/node-mongodb-native/7.0/classes/AggregationCursor.html#close\n */\n\nQueryCursor.prototype.close = async function close() {\n  if (typeof arguments[0] === 'function') {\n    throw new MongooseError('QueryCursor.prototype.close() no longer accepts a callback');\n  }\n  try {\n    await this.cursor.close();\n    this._closed = true;\n    this.emit('close');\n  } catch (error) {\n    this.listeners('error').length > 0 && this.emit('error', error);\n    throw error;\n  }\n};\n\n/**\n * Marks this cursor as destroyed. Will stop streaming and subsequent calls to\n * `next()` will error.\n *\n * @return {this}\n * @api private\n * @method _destroy","sourceCodeStart":218,"sourceCodeEnd":254,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/cursor/queryCursor.js#L218-L254","documentation":"QueryCursor#close() became a promise-only async method in Mongoose 7 when callback support was removed. Passing a function as the first argument throws immediately, mirroring the same policy on AggregationCursor, so unmigrated call sites fail loudly.","triggerScenarios":"queryCursor.close(() => {}) or queryCursor.close(function (err) {...}) — any function as the first argument to close() on a cursor from Model.find().cursor().","commonSituations":"Upgrading Mongoose 6 to 7+ with legacy streaming code untouched; shared cursor utilities still written callback-style.","solutions":["Replace cursor.close(cb) with await cursor.close(), handling errors via try/catch","Wrap for legacy callers: cursor.close().then(() => cb(null), cb)","Grep the codebase for close( calls passing functions as part of the Mongoose 7 migration checklist"],"exampleFix":"// before\nconst cursor = Book.find().cursor();\ncursor.close(function (err) {\n  if (err) console.error(err);\n});\n\n// after\nconst cursor = Book.find().cursor();\ntry {\n  await cursor.close();\n} catch (err) {\n  console.error(err);\n}","handlingStrategy":"validation","validationCode":"function closeCursor(cursor, ...args) {\n  if (args.some(a => typeof a === 'function')) {\n    throw new TypeError('close() takes no callback; await the returned promise');\n  }\n  return cursor.close();\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Use await cursor.close() exclusively in Mongoose 7+ code","Shim legacy callers at the boundary: close().then(() => cb(null), cb)","Include cursor utilities in upgrade checklists for major Mongoose versions"],"tags":["query-cursor","callback","promise","mongoose-7","migration"],"backgroundTag":"callback-api-removed","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}