Automattic/mongoose · warning · MongooseError

Aggregate not bound to any Model

Error message

Aggregate not bound to any Model

What it means

Developers frequently write new mongoose.Schema.Types.ObjectId('507f...') when they actually wanted a new ObjectId VALUE — the SchemaType constructor is for defining schema paths, not creating ids (creating one with a 24-char hex string, or with no arguments, is almost always a mistake). The constructor detects this (key is a 24-char hex string or undefined) and warns to use mongoose.Types.ObjectId instead. If you genuinely need a schema path whose key is a hex string (or you are instantiating the type with no key intentionally), pass suppressWarning: true in options.

Source

Thrown at lib/aggregate.js:1066

    }
  }

  return this._pipeline;
};

/**
 * Executes the aggregate pipeline on the currently bound Model.
 *
 * #### Example:
 *     const result = await aggregate.exec();
 *
 * @return {Promise}
 * @api public
 */

Aggregate.prototype.exec = async function exec() {
  if (!this._model && !this._connection) {
    throw new MongooseError('Aggregate not bound to any Model');
  }
  if (typeof arguments[0] === 'function') {
    throw new MongooseError('Aggregate.prototype.exec() no longer accepts a callback');
  }

  if (this._connection) {
    if (!this._pipeline.length) {
      throw new MongooseError('Aggregate has empty pipeline');
    }

    this._optionsForExec();

    const _this = this;
    return traceAggregate(async function maybeTracedConnectionAggregate() {
      const cursor = await _this._connection.client.db().aggregate(_this._pipeline, _this.options);
      return await cursor.toArray();
    }, () => ({
      operation: 'aggregate',

View on GitHub (pinned to 49cdab0136)

Solutions

  1. To create an id value: new mongoose.Types.ObjectId() or new mongoose.Types.ObjectId('507f1f77bcf86cd799439011').
  2. For default ids in a schema: { type: Schema.Types.ObjectId, default: () => new mongoose.Types.ObjectId() }.
  3. For a real schema path, pass the field name: new Schema({ owner: Schema.Types.ObjectId }).
  4. Only if you intentionally key a path by a 24-hex string: new Schema.Types.ObjectId('507f...', { suppressWarning: true }).

Example fix

// before
const id = new mongoose.Schema.Types.ObjectId('507f1f77bcf86cd799439011');

// after
const id = new mongoose.Types.ObjectId('507f1f77bcf86cd799439011');
Defensive patterns

Strategy: type-guard

Validate before calling

const { Types } = require('mongoose');
function makeId(hex) {
  // always the value class, never the SchemaType
  return hex === undefined ? new Types.ObjectId() : new Types.ObjectId(hex);
}

Type guard

const isHex24 = (s) => typeof s === 'string' && /^[a-f0-9]{24}$/i.test(s);

Prevention

When it happens

Trigger: new mongoose.Schema.Types.ObjectId('507f1f77bcf86cd799439011') to make an id value; new mongoose.Schema.Types.ObjectId() with no key; factory helpers like id => new Schema.Types.ObjectId(id) used for seeding/default ids (the right tool there is default: () => new mongoose.Types.ObjectId()).

Common situations: Confusion between mongoose.Types.ObjectId (the driver ObjectId class) and mongoose.Schema.Types.ObjectId (the SchemaType) — the classic double-namespacing trap; seeding scripts; default _id factories; refactoring where a schema-path definition lost its field-name argument.

Related errors


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