Automattic/mongoose · error · MissingSchemaError
Schema hasn't been registered for model "${name}". Use mongo
Error message
Schema hasn't been registered for model "${name}".
Use mongoose.model(name, schema) What it means
conn.model(name) with a single argument is a pure lookup against models already compiled on THIS connection. If nothing is registered under that name, Mongoose throws MissingSchemaError ('Schema hasn't been registered for model ...') at lib/connection.js:1509 — it cannot invent a schema, so the model must have been registered first, or the name/connection is wrong.
Source
Thrown at lib/connection.js:1509
// Errors handled internally, so safe to ignore error
model.init().catch(function $modelInitNoop() {});
return model;
}
if (this.models[name] && collection) {
// subclassing current model with alternate collection
model = this.models[name];
schema = model.prototype.schema;
const sub = model.__subclass(this, schema, collection);
// do not cache the sub model
return sub;
}
if (arguments.length === 1) {
model = this.models[name];
if (!model) {
throw new MongooseError.MissingSchemaError(name);
}
return model;
}
if (!model) {
throw new MongooseError.MissingSchemaError(name);
}
if (this === model.prototype.db
&& (!collection || collection === model.collection.name)) {
// model already uses this connection.
// only the first model with this name is cached to allow
// for one-offs with custom collection names etc.
if (!this.models[name]) {
this.models[name] = model;
}
View on GitHub (pinned to 49cdab0136)
Solutions
- Register first on the same connection: conn.model('User', userSchema), then look up
- Check what exists: console.log(conn.modelNames()) before the lookup
- Use the right registry: mongoose.model('User') for the default connection, conn.model('User') for a custom connection — they are separate
- Fix casing/typos; model names are case-sensitive
Example fix
// before
const conn = mongoose.createConnection(uri);
const User = conn.model('User'); // MissingSchemaError: separate registry
// after
const User = conn.model('User', userSchema); // register on this connection
// or, if registered globally: mongoose.model('User') Defensive patterns
Strategy: validation
Validate before calling
if (!conn.modelNames().includes('User')) {
conn.model('User', userSchema); // register before lookup
}
const User = conn.model('User'); Try / catch
let User;
try {
User = conn.model('User');
} catch (err) {
if (err instanceof mongoose.Error.MissingSchemaError) {
User = conn.model('User', userSchema); // first caller registers
} else {
throw err;
}
} Prevention
- Remember registries are per connection: mongoose.model and conn.model do not share
- Call conn.modelNames() when a lookup unexpectedly fails
- Ensure model files are imported before routes that use them (import order at app bootstrap)
- Model names are case-sensitive — match the registration exactly
When it happens
Trigger: conn.model('User') before conn.model('User', userSchema) has run; a case typo ('user' vs 'User' — names are case-sensitive); a model registered on a different connection (mongoose.model on the default connection vs a createConnection instance) and looked up on this one.
Common situations: Multi-connection / multi-tenant apps where models are registered per connection; import-order bugs where a route executes before the model file; mixing mongoose.model() and conn.model() registries.
Related errors
- `connection.model()` should not be run with `new`. If you ar
- The 2nd parameter to `mongoose.model()` should be a schema o
- Cannot overwrite `${name}` model once compiled.
- First parameter to `deleteModel()` must be a string or regex
- 2nd argument to `Model` constructor must be a POJO or string
AI-assisted analysis of Automattic/mongoose@49cdab0136 (2026-08-21).
Data as JSON: /api/errors/408f3428ffd1d83b.
Report an issue: GitHub.