MissingSchemaError: Schema hasn't been registered for model "User"

Viewed 84225

In my models/user.js file:

var mongoose = require('mongoose');
var Schema = mongoose.Schema;

var userSchema = new Schema({
    (define schema)
});
...
(save user)
...
(check password)
...
mongoose.model('User', userSchema);

And in my router/index.js, I have:

var mongoose = require('mongoose');
var User = mongoose.model('User');

which throws the error:

MissingSchemaError: Schema hasn't been registered for model "User".

If however, in user.js, I do (in the last line)

module.exports = mongoose.model('User', userSchema);

and in index.js I do var User = require('../models/User');, then everything works.

But it should not, because in config/pass.js I am doing var User = mongoose.model('User'); and it's working flawlessly.

The require('../models/User'); syntax isn't working on Ubuntu, but is on my Mac.

What should I do? How do I fix it? I have looked at tons of sample apps, including MEAN but nothing was really helpful.

17 Answers

I literally research lot and I found a solution so, I share this solution to you so, no one can face that cheap mistake that I did.

Please remember, you just need to add the same name in ref as you gave in your model because its case sensitive ( Product !== product ).

const Product = new mongoose.model('Product', productSchema);

product: {
    type: mongoose.Schema.ObjectId,
    ref: 'Product', <-- Should be same as modelName
    required: [true, 'Cart must belong to a product']
}

In my case, it happened because of capital/small letter confusion. User model had this:

const userSchema = new Schema({
// ...
});
module.exports = mongoose.model('User', userSchema);

And Product model had a reference to User model but small case:

const productSchema = new Schema({
// ...
  userId: {
    type: Schema.Types.ObjectId,
    ref: 'user', // This should exactly match the name of User model above!!!
    required: true
  }
});

I've also experienced this error with ES6/Typescript. Even I imported the model, the error still persisted. According to docs here

MongooseError.MissingSchemaError

Thrown when you try to access a model that has not been registered yet

    import { model, Schema } from 'mongoose';
    import Company from './CompanyModel';

    const ProjectSchema = new Schema({
        company: { type: Schema.Types.ObjectId, ref: "Company" }
    });

    export default model('Project', ProjectSchema);

The tips was just to make sure to use the model explicitly, so changing ref:"Company" into ref:Company.modelName seemed fixed it.

I hope that helps some of you

  • You'll need to require your model in your code
  • Mongoose won't recognize that you've defined a model until you've called mongoose.model, and that's only called when you require model

Ex.

In the below example, you will get MissingSchemaError: Schema hasn't been registered for model “Role” if you don't do const Role = require("./role");

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Role = require("./role");
const userSchema = new Schema(
  {
    role: { type: Schema.Types.ObjectId, ref: "Role", required: false },
    username: { type: String, required: true, trim: true },
    password: { type: String, required: true, trim: true },
    email: { type: String, required: true, trim: true }
  },
  { timestamps: true }
);

module.exports = mongoose.model("User", userSchema);

I recently came across a solution similar to the answers provided by @rajkumar-nagarajan and @verybadalloc.

I like this approach better, because it avoids the n+1 iteration, and it does not read all the models from the file system.

In app/models/index.js, require each model file:

require('./model1');
require('./model2');
require('./model3');

Then, in /app.js or /index.js (whichever your project uses), you can now simply do:

require('./app/models');

The part I'm missing (any tips appreciated here) --how to easily register each model by name like:

mongoose.model('Model1')

I was making a different mistake like I have created the Schema but the issue was that I didn't use schema model (for insert, update, read and delete the doc).

i.e. I have created the collection something like that:

const playerSchema = new Schema({
    bowling: {
        style: String,
        arm: String,
    }
})

export const PlayerSchema = model('Player', playerSchema)

but didn't use or call PlayerSchema model somewhere that's why I was getting this error.

If you are facing this error because of ref field in your schema, you need to provide exact name that you used for that modeling reference schema (its case sensitive).

// models/User.js
const userSchema = new Schema({ name: String });
module.exports = mongoose.model('User', userSchema); // note the 1st arg


// models/Post.js
const postSchema = new Schema({ 
   user: { 
     type: mongoose.Schema.Types.ObjectId, 
     ref: 'User' // `ref` must be 'User' not 'user'
   },
})

module.exports = mongoose.model('Post', postSchema)

Also while calling .populate() on query, the reference model must be modeled before calling it. This is because models/User.js is not executed anywhere else in here, so by importing you will make User available in mongoose.models object.

In a real project the User model file be imported at least once through out the project, so just make sure you have imported reference model at least once.

// your app
const User = require('./models/User') // important to import
const Post = require('./models/Post')

//console.log(!!mongoose.models.User) // true
//..
const post = await Post.findOne().populate({ path : 'user' })

Alternative way is to import User model in Post model and use it for ref field.

// models/User.js
const userSchema = new Schema({ name: String });
module.exports = mongoose.model('User', userSchema);


// models/Post.js
const User = require('./User')

const postSchema = new Schema({ 
   user: { 
     type: mongoose.Schema.Types.ObjectId, 
     ref: User, // here we are directly referring model instance itself instead of model name.
   }
});

module.exports = mongoose.model('Post', postSchema)

& of course there are many approaches for solving this issue.

I tried all the above solutions but all of them failed instead I found that the solution was to clear my database (MongoDB) and then rerunning the app

The problem arises in the require() statements for the models. You need to move all the MongoDB dependencies above the routes dependencies like this eg

//blog.js file

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

const blogSchema = new Schema({
title : String
});

mongoose.model('blogs', blogSchema);

in server.js

//server.js file
require('dotenv').config();
const mongoose = require('mongoose');
const express = require('express');
const bodyParser = require('body-parser');
const cors = require('cors');
require('./models/blog');
const Blog = mongoose.model('blogs');

const URL = process.env.MONGO_DB_URL;
 mongoose.connect(URL, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

mongoose.connection
.once('open', () => console.log('Connected to MongoLab instance.'))
.on('error', (error) => console.log('Error connecting to MongoLab:', error));

const app = express();

app.use(cors());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.get('/',  (req,res)=>{
res.send('Hello World')
});

 app.post('/blog',async (req, res) =>{
    const blog = await new Blog(req.body).save();
    res.send('just an example');
  });
Related