{"record":{"id":"eca65cc52eccbe07","repo":"Automattic/mongoose","slug":"first-argument-to-model-constructor-must-be-an-o","errorCode":null,"errorMessage":"First argument to `Model` constructor must be an object, **not** a string. Make sure you're calling `mongoose.model()`, not `mongoose.Model()`.","messagePattern":"First argument to `Model` constructor must be an object, \\*\\*not\\*\\* a string\\. Make sure you're calling `mongoose\\.model\\(\\)`, not `mongoose\\.Model\\(\\)`\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"lib/model.js","lineNumber":139,"sourceCode":" * @param {object} [options] optional object containing the options for the document.\n * @param {boolean} [options.defaults=true] if `false`, skip applying default values to this document.\n * @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.\n * @inherits Document https://mongoosejs.com/docs/api/document.html\n * @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.\n * @event `index`: Emitted after `Model#ensureIndexes` completes. If an error occurred it is passed with the event.\n * @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.\n * @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.\n * @api public\n */\n\nfunction Model(doc, fields, options) {\n  if (fields instanceof Schema) {\n    throw new TypeError('2nd argument to `Model` constructor must be a POJO or string, ' +\n      '**not** a schema. Make sure you\\'re calling `mongoose.model()`, not ' +\n      '`mongoose.Model()`.');\n  }\n  if (typeof doc === 'string') {\n    throw new TypeError('First argument to `Model` constructor must be an object, ' +\n      '**not** a string. Make sure you\\'re calling `mongoose.model()`, not ' +\n      '`mongoose.Model()`.');\n  }\n  Document.call(this, doc, fields, options);\n}\n\n/**\n * Inherits from Document.\n *\n * All Model.prototype features are available on\n * top level (non-sub) documents.\n * @api private\n */\n\nObject.setPrototypeOf(Model.prototype, Document.prototype);\nModel.prototype.$isMongooseModelPrototype = true;\n\n/**","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/Automattic/mongoose/blob/49cdab01366679723b487ecb754b38570f783289/lib/model.js#L121-L157","documentation":"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.","triggerScenarios":"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'`.","commonSituations":"Autocomplete picking Model over model; tutorials and snippets mixing the two names; refactors that rename the mongoose import and leave a bare Model(...) call.","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"],"exampleFix":"// before\nimport { Model, Schema } from 'mongoose';\nconst User = Model('User', userSchema); // TypeError\n\n// after\nimport mongoose from 'mongoose';\nconst User = mongoose.model('User', userSchema);","handlingStrategy":"type-guard","validationCode":"// Guard a factory helper against string-first Model calls\nfunction registerModel(name, schema) {\n  if (typeof name !== 'string' || !(schema instanceof mongoose.Schema)) {\n    throw new TypeError('Use mongoose.model(name, schema)');\n  }\n  return mongoose.model(name, schema);\n}","typeGuard":"const isDocumentInput = (doc) => doc != null && typeof doc === 'object' && !Array.isArray(doc);","tryCatchPattern":"try {\n  const M = mongoose.Model('User', schema);\n} catch (err) {\n  if (err instanceof TypeError && /First argument to `Model`/.test(err.message)) {\n    // use mongoose.model('User', schema) instead\n  } else throw err;\n}","preventionTips":["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"],"tags":["mongoose","model","constructor","api-misuse"],"backgroundTag":"model-constructor-misuse","analyzedSha":"49cdab01366679723b487ecb754b38570f783289","analyzedAt":"2026-08-21T22:54:00.882Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}