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

Javascriptnode.jsExpressMongoose

Javascript Problem Overview


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.

Javascript Solutions


Solution 1 - Javascript

I got the same problem when I am trying the MEAN tutorial.

After done a little bit research, I found that in app.js, if I put require("./models/User") before var routes = require("./routes/index"), then it works.

Like this:


mongoose.connect("mongodb://localhost/news");
require("./models/Posts");
require("./models/Comments");

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

Hope the answer will be helpful!

Solution 2 - Javascript

The error occurs because the models/user.js has not been interpreted by the time router/index.js has been loaded. One way to solve this would be to do the following:

var mongoose = require('mongoose');
//Load all your models
var User = require('./../models/user.js');

//Now, this call won't fail because User has been added as a schema.
mongoose.model('User');

This, however, turns out to be against best practises, which dictates that all this config stuff should happen at the start of your app.js file. Look at this example from madhums' example project

var models_path = __dirname + '/app/models'
fs.readdirSync(models_path).forEach(function (file) {
  if (~file.indexOf('.js')) require(models_path + '/' + file)
})

Note that he is loading his models before setting the app's router. As for the Ubuntu vs Mac issue, I believe it is because a relative path in Ubuntu has to start with ./. You just have to change it to ./../models/user.js, which works on Mac.

Solution 3 - Javascript

All code in your mongoose schema js files should have run before it is used in other files.

For example, the following code snippet makes sure the mongoose schema files/modules are executed.

> fs.readdirSync(__dirname + '/app/models').forEach(function (file) { > if (~file.indexOf('.js')) require(__dirname + '/app/models/' + file); });

or schema files can be manually executed by calling

> var User = require('./app/models/user.js')

before the models are used anywhere in the application.

Once the above is done, other modules that uses mongoose models can be required/executed.

Solution 4 - Javascript

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']
}

Solution 5 - Javascript

This problem occurred when try to get model before load the model file load

I solved same problem in my mean.io project

In controller:

'use strict';
require('../models/settingsModel'); // load settingsModel.js file before get mongoose.model('Settings')
var mongoose = require('mongoose'),
    Settings = mongoose.model('Settings'),
    Q = require('q');

Solution 6 - Javascript

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
  }
});

Solution 7 - Javascript

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

Solution 8 - Javascript

  • 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);

Solution 9 - Javascript

In using express, one of the common mistake is by requiring the express before mongoose. This results to "MissingSchemaError: Schema hasn't been registered for model "User"." error.

You can easily fix it by correcting the "require" order (i.e mongoose then express)

var mongoose = require('./config/mongoose'), 
    express = require('./config/express');

Solution 10 - Javascript

I got this error while trying to use mongoose-fixture to seed some default data into a mongo collection. Was baffled for long, following this and similar threads for help, trying to debug. Ultimately the issue turned out to be due to mongoose and mongoose-fixture versions in my case.

If no code changes help, or if you get this error while trying to correctly use mongoose-fixture (which is supposed to register your schemas for you), try this. Delete the node_modules dir of your project, run an npm cache clean, and then an npm install.

If even this doesn't help, try comparing versions of mongoose / mongoose-fixture between the problematic app and one that works, and try changing the version in your package.json, and repeating the above steps. This worked for me.

Solution 11 - Javascript

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')

Solution 12 - Javascript

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.

Solution 13 - Javascript

I encountered this issue when tried to add a new model on the base code of this tutorial User Auth on MEAN stack. The solution is like what Ahei mentioned.

Specifically, I need to add a line require('path/to/your/model') in the end of /app_api/models/db.js which is required in the app.js. It is better to keep the consistency of the structure for the ease of development.

Solution 14 - Javascript

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

Solution 15 - Javascript

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');
  });

Solution 16 - Javascript

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.

Solution 17 - Javascript

If you are using the Mean.js stack, run the test with:

grunt test

And not with

mocha

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKGoView Question on Stackoverflow
Solution 1 - JavascriptAhei ChengView Answer on Stackoverflow
Solution 2 - JavascriptverybadallocView Answer on Stackoverflow
Solution 3 - JavascriptRajkumar NagarajanView Answer on Stackoverflow
Solution 4 - JavascriptNisharg ShahView Answer on Stackoverflow
Solution 5 - JavascriptShaishab RoyView Answer on Stackoverflow
Solution 6 - JavascriptAtilla BaspinarView Answer on Stackoverflow
Solution 7 - JavascriptirzhyView Answer on Stackoverflow
Solution 8 - JavascriptVaibhav KBView Answer on Stackoverflow
Solution 9 - JavascriptWreeecksView Answer on Stackoverflow
Solution 10 - JavascriptAvik RayView Answer on Stackoverflow
Solution 11 - JavascripttheUtherSideView Answer on Stackoverflow
Solution 12 - JavascriptWasiFView Answer on Stackoverflow
Solution 13 - JavascriptpeteroidView Answer on Stackoverflow
Solution 14 - JavascriptBugView Answer on Stackoverflow
Solution 15 - JavascriptTikaram MardiView Answer on Stackoverflow
Solution 16 - JavascriptbogdanoffView Answer on Stackoverflow
Solution 17 - JavascriptMaçoisView Answer on Stackoverflow