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
- Wrap the definition: conn.model('Test', new Schema({ name: String }))
- Or pass a POJO and let Mongoose convert: conn.model('Test', { name: String })
- 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
- Always construct schemas explicitly: new Schema({...})
- In TypeScript, type model parameters as (name: string, schema: Schema | Record<string, any>)
- Remember a string 2nd argument is silently treated as a collection name — avoid relying on it accidentally
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
- First parameter to `deleteModel()` must be a string or regex
- 2nd argument to `Model` constructor must be a POJO or string
- `connection.model()` should not be run with `new`. If you ar
- First argument to `Model` constructor must be an object, **n
- Aggregate `near()` must be called with non-nullish argument
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/dd7d50db7c291d30.
Report an issue: GitHub.