Automattic/mongoose · error · MongooseError

QueryCursor.prototype.close() no longer accepts a callback

Error message

QueryCursor.prototype.close() no longer accepts a callback

What it means

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.

Source

Thrown at lib/cursor/queryCursor.js:236

QueryCursor.prototype._markError = function(error) {
  this._error = error;
  return this;
};

/**
 * Marks this cursor as closed. Will stop streaming and subsequent calls to
 * `next()` will error.
 *
 * @return {Promise}
 * @api public
 * @method close
 * @emits close
 * @see AggregationCursor.close https://mongodb.github.io/node-mongodb-native/7.0/classes/AggregationCursor.html#close
 */

QueryCursor.prototype.close = async function close() {
  if (typeof arguments[0] === 'function') {
    throw new MongooseError('QueryCursor.prototype.close() no longer accepts a callback');
  }
  try {
    await this.cursor.close();
    this._closed = true;
    this.emit('close');
  } catch (error) {
    this.listeners('error').length > 0 && this.emit('error', error);
    throw error;
  }
};

/**
 * Marks this cursor as destroyed. Will stop streaming and subsequent calls to
 * `next()` will error.
 *
 * @return {this}
 * @api private
 * @method _destroy

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Replace cursor.close(cb) with await cursor.close(), handling errors via try/catch
  2. Wrap for legacy callers: cursor.close().then(() => cb(null), cb)
  3. Grep the codebase for close( calls passing functions as part of the Mongoose 7 migration checklist

Example fix

// before
const cursor = Book.find().cursor();
cursor.close(function (err) {
  if (err) console.error(err);
});

// after
const cursor = Book.find().cursor();
try {
  await cursor.close();
} catch (err) {
  console.error(err);
}
Defensive patterns

Strategy: validation

Validate before calling

function closeCursor(cursor, ...args) {
  if (args.some(a => typeof a === 'function')) {
    throw new TypeError('close() takes no callback; await the returned promise');
  }
  return cursor.close();
}

Prevention

When it happens

Trigger: queryCursor.close(() => {}) or queryCursor.close(function (err) {...}) — any function as the first argument to close() on a cursor from Model.find().cursor().

Common situations: Upgrading Mongoose 6 to 7+ with legacy streaming code untouched; shared cursor utilities still written callback-style.

Related errors


AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21). Data as JSON: /api/errors/2f3d565540fdd408. Report an issue: GitHub.