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
- Drop the callback and await the promise: `await query.validate(castedDoc, options, isOverwriting)`.
- If you need error handling, use try/catch or .catch() around the awaited call.
- Search the codebase for `validate(` calls on Query objects that pass a function and remove them all at once.
- 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
- Run the Mongoose 7 migration guide's callback sweep (grep for ', cb' / '(err,').
- Enable a lint rule or codemod that flags function arguments to async APIs.
- Treat all Mongoose query methods as promise-only.
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
- Model.init() no longer accepts a callback
- Model.createCollection() no longer accepts a callback
- Model.syncIndexes() no longer accepts a callback
- Model.cleanIndexes() no longer accepts a callback
- Model.listIndexes() no longer accepts a callback
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/0b8f5ccda02a3fe1.
Report an issue: GitHub.