{"record":{"id":"0b8f5ccda02a3fe1","repo":"Automattic/mongoose","slug":"query-prototype-validate-no-longer-accepts-a-cal","errorCode":null,"errorMessage":"Query.prototype.validate() no longer accepts a callback","messagePattern":"Query\\.prototype\\.validate\\(\\) no longer accepts a callback","errorType":"exception","errorClass":"MongooseError","httpStatus":null,"severity":"error","filePath":"lib/query.js","lineNumber":4182,"sourceCode":"  return preview;\n}\n\n/**\n * Mongoose calls this function internally to validate the query if\n * `runValidators` is set\n *\n * @param {object} castedDoc the update, after casting\n * @param {object} options the options from `_optionsForExec()`\n * @param {boolean} isOverwriting\n * @method validate\n * @memberOf Query\n * @instance\n * @api private\n */\n\nQuery.prototype.validate = async function validate(castedDoc, options, isOverwriting) {\n  if (typeof arguments[3] === 'function') {\n    throw new MongooseError('Query.prototype.validate() no longer accepts a callback');\n  }\n\n  await _executePreHooks(this, 'validate');\n\n  if (isOverwriting) {\n    await castedDoc.$validate();\n  } else {\n    const validationErrors = await updateValidators(this, this.model.schema, castedDoc, options);\n    if (validationErrors.length > 0) {\n      const err = new ValidationError(null);\n      for (const validationError of validationErrors) {\n        err.addError(validationError.path, validationError);\n      }\n      throw err;\n    }\n  }\n\n  await _executePostHooks(this, null, null, 'validate');","sourceCodeStart":4164,"sourceCodeEnd":4200,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/query.js#L4164-L4200","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before (Mongoose 6)\nquery.validate(castedDoc, options, isOverwriting, (err) => { ... });\n\n// after (Mongoose 7+)\ntry {\n  await query.validate(castedDoc, options, isOverwriting);\n} catch (err) { ... }","handlingStrategy":"type-guard","validationCode":"if (typeof lastArg === 'function') { throw new Error('Callbacks are removed in Mongoose 7+; await the promise'); }","typeGuard":"const hasCallback = (...args) => args.length > 0 && typeof args[args.length - 1] === 'function';","tryCatchPattern":"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; }","preventionTips":["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."],"tags":["mongoose","callback-removed","migration","promise"],"backgroundTag":"mongoose-callbacks-removed","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}