Automattic/mongoose · error · MongooseError
Query must have an associated model before executing
Error message
Query must have an associated model before executing
What it means
exec() needs a Model to know which collection to hit and which schema to use for casting. If `query.model` is null — typically because the Query was constructed standalone instead of through a model — Mongoose throws before executing. Model-derived queries (Model.find(), doc.$where, etc.) always carry the model, so this error almost always means a raw `new Query()` was used.
Source
Thrown at lib/query.js:4758
* @return {Promise}
* @api public
*/
Query.prototype.exec = async function exec(op) {
if (typeof op === 'function' || (arguments.length >= 2 && typeof arguments[1] === 'function')) {
throw new MongooseError('Query.prototype.exec() no longer accepts a callback');
}
this._validateOp();
if (typeof op === 'string') {
this.op = op;
}
if (this.op == null) {
throw new MongooseError('Query must have `op` before executing');
}
if (this.model == null) {
throw new MongooseError('Query must have an associated model before executing');
}
const thunk = opToThunk.get(this.op);
if (!thunk) {
throw new MongooseError('Query has invalid `op`: "' + this.op + '"');
}
if (this.options?.sort && typeof this.options.sort === 'object' && Object.hasOwn(this.options.sort, '')) {
throw new MongooseError('Invalid field "" passed to sort()');
}
if (this._execCount > 0) {
let str = this.toString();
if (str.length > 60) {
str = str.slice(0, 60) + '...';
}
throw new MongooseError('Query was already executed: ' + str);
}View on GitHub (pinned to 49cdab0136)
Solutions
- Create queries through a model: `Model.find({...}).exec()` instead of `new Query(...)`.
- If you must reuse a standalone query, bind it first: `query.model = MyModel` (or construct it as `new Query({}, null, Model)`).
- Keep raw query objects as plain filter documents and pass them into Model.find(filter) at execution time.
Example fix
// before
const { Query } = require('mongoose');
await new Query({ name: 'x' }).find().exec(); // throws: Query must have an associated model
// after
await Model.find({ name: 'x' }).exec(); Defensive patterns
Strategy: validation
Validate before calling
function execQuery(query, Model) {
if (query.model == null) query.model = Model;
return query.exec();
} Type guard
const queryHasModel = (q) => q.model != null;
Try / catch
try { await q.exec(); } catch (err) { if (err instanceof mongoose.Error && /associated model/.test(err.message)) { q.model = MyModel; return q.exec(); } throw err; } Prevention
- Always create queries via Model.find() and friends.
- Store plain filter objects, not bare Query instances, for reuse.
- Bind a model explicitly when constructing Query manually: new Query({}, null, Model).
When it happens
Trigger: `new Query({ name: 'x' }).find().exec()` with no model bound; `new mongoose.Query()` then .find().exec(); losing the model by manually cloning query internals; calling exec on a query created from a deleted/undefined model variable.
Common situations: Using Query directly to build reusable filter objects and then executing them by mistake; dependency-order bugs where the query outlives its model import; porting mquery code into Mongoose.
Related errors
- Query must have `op` before executing
- Query has invalid `op`: "${this.op}"
- Invalid addFields() argument. Must be an object
- Query filter must be an object, got an array ${util.inspect(
- Cast to Array failed for value "${value}" at path "${path}"
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/eb5a5351ca6330b6.
Report an issue: GitHub.