Automattic/mongoose · error · TypeError
First argument to `Model` constructor must be an object, **n
Error message
First argument to `Model` constructor must be an object, **not** a string. Make sure you're calling `mongoose.model()`, not `mongoose.Model()`.
What it means
Companion guard in the Model constructor: the first argument must be a document object, not a string. Calling mongoose.Model('User') or new mongoose.Model('User', ...) — using the Model constructor where the mongoose.model(name, schema) registry function is meant — throws this TypeError immediately instead of producing a broken object.
Source
Thrown at lib/model.js:139
* @param {object} [options] optional object containing the options for the document.
* @param {boolean} [options.defaults=true] if `false`, skip applying default values to this document.
* @param {boolean} [options.skipId=false] By default, Mongoose document if one is not provided and the document's schema does not override Mongoose's default `_id`. Set `skipId` to `true` to skip this generation step.
* @inherits Document https://mongoosejs.com/docs/api/document.html
* @event `error`: If listening to this event, 'error' is emitted when a document was saved and an `error` occurred. If not listening, the event bubbles to the connection used to create this Model.
* @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event.
* @event `index-single-start`: Emitted when an individual index starts within `Model#ensureIndexes`. The fields and options being used to build the index are also passed with the event.
* @event `index-single-done`: Emitted when an individual index finishes within `Model#ensureIndexes`. If an error occurred it is passed with the event. The fields, options, and index name are also passed.
* @api public
*/
function Model(doc, fields, options) {
if (fields instanceof Schema) {
throw new TypeError('2nd argument to `Model` constructor must be a POJO or string, ' +
'**not** a schema. Make sure you\'re calling `mongoose.model()`, not ' +
'`mongoose.Model()`.');
}
if (typeof doc === 'string') {
throw new TypeError('First argument to `Model` constructor must be an object, ' +
'**not** a string. Make sure you\'re calling `mongoose.model()`, not ' +
'`mongoose.Model()`.');
}
Document.call(this, doc, fields, options);
}
/**
* Inherits from Document.
*
* All Model.prototype features are available on
* top level (non-sub) documents.
* @api private
*/
Object.setPrototypeOf(Model.prototype, Document.prototype);
Model.prototype.$isMongooseModelPrototype = true;
/**View on GitHub (pinned to 49cdab0136)
Solutions
- Use mongoose.model('User', userSchema) to register and compile the model
- Keep an imported Model only for typing/extends (class User extends Model<User>), never as a callable factory
Example fix
// before
import { Model, Schema } from 'mongoose';
const User = Model('User', userSchema); // TypeError
// after
import mongoose from 'mongoose';
const User = mongoose.model('User', userSchema); Defensive patterns
Strategy: type-guard
Validate before calling
// Guard a factory helper against string-first Model calls
function registerModel(name, schema) {
if (typeof name !== 'string' || !(schema instanceof mongoose.Schema)) {
throw new TypeError('Use mongoose.model(name, schema)');
}
return mongoose.model(name, schema);
} Type guard
const isDocumentInput = (doc) => doc != null && typeof doc === 'object' && !Array.isArray(doc);
Try / catch
try {
const M = mongoose.Model('User', schema);
} catch (err) {
if (err instanceof TypeError && /First argument to `Model`/.test(err.message)) {
// use mongoose.model('User', schema) instead
} else throw err;
} Prevention
- Remember: lowercase model() registers, uppercase Model is a base class
- Let the linter catch calling imported Model as a function (no-call-on-imported-class style rules)
- Prefer `import mongoose` default-import style to keep the model() factory obvious
When it happens
Trigger: const User = mongoose.Model('User', userSchema) or new mongoose.Model('User'); confusion between mongoose.model (lowercase, factory/registry) and mongoose.Model (uppercase, base class), often after `import { Model } from 'mongoose'`.
Common situations: Autocomplete picking Model over model; tutorials and snippets mixing the two names; refactors that rename the mongoose import and leave a bare Model(...) call.
Related errors
- 2nd argument to `Model` constructor must be a POJO or string
- Invalid arguments
- Aggregate.prototype.exec() no longer accepts a callback
- `connection.model()` should not be run with `new`. If you ar
- The 2nd parameter to `mongoose.model()` should be a schema o
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/eca65cc52eccbe07.
Report an issue: GitHub.