Automattic/mongoose · error · MongooseError

The 2nd parameter to `mongoose.model()` should be a schema o

Error message

The 2nd parameter to `mongoose.model()` should be a schema or a POJO

What it means

When compiling a model, connection.model(name, schema) accepts a Schema instance, a plain object (auto-wrapped with new Schema(obj)), a string (reinterpreted as the collection name, leaving schema falsy), or a falsy value. Anything else that reaches the final check — a class/function (ES/TS classes are functions), an array, a number, true — fails schema.instanceOfSchema and throws (lib/connection.js:1466).

Source

Thrown at lib/connection.js:1463

    fn = name;
    name = fn.name;
  }

  // collection name discovery
  if (typeof schema === 'string') {
    collection = schema;
    schema = false;
  }

  if (utils.isObject(schema)) {
    if (!schema.instanceOfSchema) {
      schema = new Schema(schema);
    } else if (!(schema instanceof this.base.Schema)) {
      schema = schema._clone(this.base.Schema);
    }
  }
  if (schema && !schema.instanceOfSchema) {
    throw new MongooseError('The 2nd parameter to `mongoose.model()` should be a ' +
      'schema or a POJO');
  }

  const defaultOptions = { cache: false, overwriteModels: this.base.options.overwriteModels };
  const opts = Object.assign(defaultOptions, options, { connection: this });
  if (this.models[name] && !collection && opts.overwriteModels !== true) {
    // model exists but we are not subclassing with custom collection
    if (schema?.instanceOfSchema && schema !== this.models[name].schema) {
      throw new MongooseError.OverwriteModelError(name);
    }
    return this.models[name];
  }

  let model;

  if (schema?.instanceOfSchema) {
    applyPlugins(schema, this.plugins, null, '$connectionPluginsApplied');

View on GitHub (pinned to 49cdab0136)

Solutions

  1. Wrap the definition: conn.model('Test', new Schema({ name: String }))
  2. Or pass a POJO and let Mongoose convert: conn.model('Test', { name: String })
  3. If you meant to pass a class, it belongs in the 1st parameter: conn.model(ClassName, schema)

Example fix

// before
conn.model('User', UserSchemaClass);

// after
conn.model('User', new Schema({ name: String }));
Defensive patterns

Strategy: type-guard

Validate before calling

function isValidModelSchema(v) {
  return v == null || typeof v === 'string' || v?.instanceOfSchema === true ||
    Object.prototype.toString.call(v) === '[object Object]';
}
if (!isValidModelSchema(schema)) {
  throw new TypeError('2nd arg to model() must be a Schema, POJO, or collection-name string');
}

Type guard

const isSchemaOrPojo = (v) =>
  v?.instanceOfSchema === true ||
  (typeof v === 'object' && v !== null && Object.prototype.toString.call(v) === '[object Object]');

Prevention

When it happens

Trigger: conn.model('Test', SomeClass) passing a class where a schema is expected; conn.model('Test', ['name']); conn.model('Test', 42); a schema-shaped object from another library that is not a Mongoose Schema.

Common situations: TypeScript users passing a decorated or extended class as the schema; forgetting new Schema({...}); passing serialized JSON strings or config arrays as definitions.

Understand the failure class

Background: Invalid argument type errors: "must be of type string", "expected X, got Y", and ERR_INVALID_ARG_TYPE explained — this error's family across 15 libraries.

Related errors


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