Automattic/mongoose · error · MongooseError

Query.prototype.validate() no longer accepts a callback

Error message

Query.prototype.validate() no longer accepts a callback

What it means

Mongoose 7 removed callback-style APIs, and this internal validation gate in Query.prototype.validate() enforces it: if a fourth argument is a function, Mongoose throws instead of silently ignoring it. The method is async and resolves with the validation result, so the old `query.validate(castedDoc, options, isOverwriting, callback)` pattern from Mongoose 6 and earlier is now a hard error.

Source

Thrown at lib/query.js:4182

  return preview;
}

/**
 * Mongoose calls this function internally to validate the query if
 * `runValidators` is set
 *
 * @param {object} castedDoc the update, after casting
 * @param {object} options the options from `_optionsForExec()`
 * @param {boolean} isOverwriting
 * @method validate
 * @memberOf Query
 * @instance
 * @api private
 */

Query.prototype.validate = async function validate(castedDoc, options, isOverwriting) {
  if (typeof arguments[3] === 'function') {
    throw new MongooseError('Query.prototype.validate() no longer accepts a callback');
  }

  await _executePreHooks(this, 'validate');

  if (isOverwriting) {
    await castedDoc.$validate();
  } else {
    const validationErrors = await updateValidators(this, this.model.schema, castedDoc, options);
    if (validationErrors.length > 0) {
      const err = new ValidationError(null);
      for (const validationError of validationErrors) {
        err.addError(validationError.path, validationError);
      }
      throw err;
    }
  }

  await _executePostHooks(this, null, null, 'validate');

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Drop the callback and await the promise: `await query.validate(castedDoc, options, isOverwriting)`.
  2. If you need error handling, use try/catch or .catch() around the awaited call.
  3. Search the codebase for `validate(` calls on Query objects that pass a function and remove them all at once.
  4. Consult the Mongoose 7 migration guide (Migrating from 6.x to 7.x) for the full list of removed callbacks.

Example fix

// before (Mongoose 6)
query.validate(castedDoc, options, isOverwriting, (err) => { ... });

// after (Mongoose 7+)
try {
  await query.validate(castedDoc, options, isOverwriting);
} catch (err) { ... }
Defensive patterns

Strategy: type-guard

Validate before calling

if (typeof lastArg === 'function') { throw new Error('Callbacks are removed in Mongoose 7+; await the promise'); }

Type guard

const hasCallback = (...args) => args.length > 0 && typeof args[args.length - 1] === 'function';

Try / catch

try { await query.validate(doc, opts, overwriting); } catch (err) { if (err instanceof mongoose.Error && /no longer accepts a callback/.test(err.message)) { /* remove the callback argument and retry once */ } throw err; }

Prevention

When it happens

Trigger: Calling `query.validate(a, b, c, callback)` with a function as the 4th argument; running pre-Mongoose-7 code (or tutorials) that pass callbacks after upgrading; wrapper libraries that still forward a callback into query.validate.

Common situations: Upgrading a codebase from Mongoose 5/6 to 7+ without running the migration guide's callback sweep; old plugins or ORM wrappers that inject callbacks into every query method.

Related errors


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