Cannot overwrite model once compiled Mongoose

node.jsMongodbModelExpressMongoose

node.js Problem Overview


Not Sure what I'm doing wrong, here is my check.js

var db = mongoose.createConnection('localhost', 'event-db');
db.on('error', console.error.bind(console, 'connection error:'));

var a1= db.once('open',function(){
var user = mongoose.model('users',{ 
       name:String,
       email:String,
       password:String,
       phone:Number,
      _enabled:Boolean
     });

user.find({},{},function (err, users) {
    mongoose.connection.close();
    console.log("Username supplied"+username);
    //doSomethingHere })
    });

and here is my insert.js

var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/event-db')

var user = mongoose.model('users',{
     name:String,
     email:String,
     password: String,
     phone:Number,
     _enabled:Boolean
   });

var new_user = new user({
     name:req.body.name,
     email: req.body.email,
     password: req.body.password,
     phone: req.body.phone,
     _enabled:false
   });

new_user.save(function(err){
    if(err) console.log(err); 
   });

Whenever I'm trying to run check.js, I'm getting this error

Cannot overwrite 'users' model once compiled.

I understand that this error comes due to mismatching of Schema, but I cannot see where this is happening ? I'm pretty new to mongoose and nodeJS.

Here is what I'm getting from the client interface of my MongoDB:

MongoDB shell version: 2.4.6 connecting to: test 
> use event-db 
  switched to db event-db 
> db.users.find() 
  { "_id" : ObjectId("52457d8718f83293205aaa95"), 
    "name" : "MyName", 
    "email" : "[email protected]", 
    "password" : "myPassword", 
    "phone" : 900001123, 
    "_enable" : true 
  } 
>

node.js Solutions


Solution 1 - node.js

Another reason you might get this error is if you use the same model in different files but your require path has a different case.

For example, in my situation I had require('./models/User') in one file, and then in another file where I needed access to the User model, I had require('./models/user').

I guess the lookup for modules & mongoose is treating it as a different file. Once I made sure the case matched in both it was no longer an issue.

Solution 2 - node.js

The error is occurring because you already have a schema defined, and then you are defining the schema again. Generally what you should do is instantiate the schema once, and then have a global object call it when it needs it.

For example:

user_model.js

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

var userSchema = new Schema({
   name:String,
   email:String,
   password:String,
   phone:Number,
   _enabled:Boolean
});
module.exports = mongoose.model('users', userSchema);          

check.js

var mongoose = require('mongoose');
var User = require('./user_model.js');

var db = mongoose.createConnection('localhost', 'event-db');
db.on('error', console.error.bind(console, 'connection error:'));
var a1= db.once('open',function(){
  User.find({},{},function (err, users) {
    mongoose.connection.close();
    console.log("Username supplied"+username);
    //doSomethingHere 
  })
});

insert.js

var mongoose = require('mongoose');
var User = require('./user_model.js');

mongoose.connect('mongodb://localhost/event-db');
var new_user = new User({
    name:req.body.name
  , email: req.body.email
  , password: req.body.password
  , phone: req.body.phone
  , _enabled:false 
});
new_user.save(function(err){
  if(err) console.log(err); 
});

Solution 3 - node.js

I had this issue while 'watching' tests. When the tests were edited, the watch re-ran the tests, but they failed due to this very reason.

I fixed it by checking if the model exists then use it, else create it.

import mongoose from 'mongoose';
import user from './schemas/user';

export const User = mongoose.models.User || mongoose.model('User', user);

Solution 4 - node.js

I had this issue while unit testing.

The first time you call the model creation function, mongoose stores the model under the key you provide (e.g. 'users'). If you call the model creation function with the same key more than once, mongoose won't let you overwrite the existing model.

You can check if the model already exists in mongoose with:

let users = mongoose.model('users')

This will throw an error if the model does not exist, so you can wrap it in a try/catch in order to either get the model, or create it:

let users
try {
  users = mongoose.model('users')
} catch (error) {
  users = mongoose.model('users', <UsersSchema...>)
}

Solution 5 - node.js

If you are using Serverless offline and don't want to use --skipCacheInvalidation, you can very well use:

module.exports = mongoose.models.Users || mongoose.model('Users', UsersSchema);

Solution 6 - node.js

I have been experiencing this issue & it was not because of the schema definitions but rather of serverless offline mode - I just managed to resolve it with this:

serverless offline --skipCacheInvalidation

Which is mentioned here https://github.com/dherault/serverless-offline/issues/258

Hopefully that helps someone else who is building their project on serverless and running offline mode.

Solution 7 - node.js

If you made it here it is possible that you had the same problem i did. My issue was that i was defining another model with the same name. I called my gallery and my file model "File". Darn you copy and paste!

Solution 8 - node.js

I solved this by adding

mongoose.models = {}

before the line :

mongoose.model(<MODEL_NAME>, <MODEL_SCHEMA>)

Hope it solves your problem

Solution 9 - node.js

This happened to me when I write like this:

import User from '../myuser/User.js';

However, the true path is '../myUser/User.js'

Solution 10 - node.js

To Solve this check if the model exists before to do the creation:

if (!mongoose.models[entityDBName]) {
  return mongoose.model(entityDBName, entitySchema);
}
else {
  return mongoose.models[entityDBName];
}

Solution 11 - node.js

I know there is an accepted solution but I feel that the current solution results in a lot of boilerplate just so that you can test Models. My solution is essentially to take you model and place it inside of a function resulting in returning the new Model if the Model has not been registered but returning the existing Model if it has.

function getDemo () {
  // Create your Schema
  const DemoSchema = new mongoose.Schema({
    name: String,
    email: String
  }, {
    collection: 'demo'
  })
  // Check to see if the model has been registered with mongoose
  // if it exists return that model
  if (mongoose.models && mongoose.models.Demo) return mongoose.models.Demo
  // if no current model exists register and return new model
  return mongoose.model('Demo', DemoSchema)
}

export const Demo = getDemo()

Opening and closing connections all over the place is frustrating and does not compress well.

This way if I were to require the model two different places or more specifically in my tests I would not get errors and all the correct information is being returned.

Solution 12 - node.js

This may give a hit for some, but I got the error as well and realized that I just misspelled the user model on importing.

wrong: const User = require('./UserModel'); correct: const User = require('./userModel');

Unbelievable but consider it.

Solution 13 - node.js

Click [here](https://github.com/vercel/next.js/blob/canary/examples/with-mongodb-mongoose/models/Pet.js "Official next-mongo-mongoose example")! Official example. Most important! thing is to export like this

export default mongoose.models.Item || mongoose.model('Item', itemsSchema)

Solution 14 - node.js

This problem might occur if you define 2 different schema's with same Collection name

Solution 15 - node.js

What you can also do is at your export, make sure to export an existing instance if one exists.

Typescript solution:

import { Schema, Document, model, models } from 'mongoose';

const UserSchema: Schema = new Schema({
    name: {
        type: String
    }
});

export interface IUser extends Document {
    name: string
}

export default models.Users || model<IUser>('Users', UserSchema);

Solution 16 - node.js

There is another way to throw this error.

Keep in mind that the path to the model is case sensitive.

In this similar example involving the "Category" model, the error was thrown under these conditions:

  1. The require statement was mentioned in two files: ..category.js and ..index.js
  2. I the first, the case was correct, in the second file it was not as follows:

category.js

enter image description here

index.js

enter image description here

Solution 17 - node.js

I solved this issue by doing this

// Created Schema - Users
// models/Users.js
const mongoose = require("mongoose");

const Schema = mongoose.Schema;

export const userSchema = new Schema({
  // ...
});

Then in other files

// Another file
// index.js
import { userSchema } from "../models/Users";
const conn = mongoose.createConnection(process.env.CONNECTION_STRING, {
    useNewUrlParser: true,
    useUnifiedTopology: true,
});
conn.models = {};
const Users = conn.model("Users", userSchema);
const results = await Users.find({});

Better Solution

let User;
try {
  User = mongoose.model("User");
} catch {
  User = mongoose.model("User", userSchema);
}

I hope this helps...

Solution 18 - node.js

Here is one more reason why this can happen. Perhaps this can help someone else. Notice the difference, Members vs Member. They must be the same...

export default mongoose.models.Members || mongoose.model('Member', FamilySchema)

Change to:

export default mongoose.models.Member || mongoose.model('Member', FamilySchema)

Solution 19 - node.js

I faced the same Issue with NextJS and MongoDB atlas. I had a models folder with the model of session stored, but the problem was not that I defined the Schema twice.

  1. Make sure the Collection is empty and does not have a previous Document
  2. If it does, then Simply declare a Model without Schema, like this:
const Session = mongoose.model("user_session_collection")
  1. You can delete the previous records or backup them, create the schema and then apply query on the database.

Hope it helped

Solution 20 - node.js

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

const userSchema = new Schema({
    name: String,
});

// Trying to get the existing model to avoid OverwriteModelError
module.exports = mongoose.model("user") || mongoose.model('user', userSchema);

Solution 21 - node.js

Below is the full solution to similar problem when using Mongoose with Pagination in combination with Nuxt and Typescript:

import {model, models, Schema, PaginateModel, Document } from 'mongoose';

import { default as mongoosePaginate } from 'mongoose-paginate-v2';

export interface IUser extends Document {
    name: string;
}

const UserSchema: Schema = new Schema({
    name: String
});

UserSchema.plugin(mongoosePaginate)

interface User<T extends Document> extends PaginateModel<T> {}


const User: User<IUser> = models['User'] as User<IUser> || model<IUser>('User', UserSchema) as User<IUser>;

export default User

tsconfig.json:

{
    "compilerOptions": {
        "target": "ES2018",
        "module": "ESNext",
        "moduleResolution": "Node",
        "lib": ["ESNext", "ESNext.AsyncIterable", "DOM"],
        "esModuleInterop": true,
        "allowJs": true,
        "sourceMap": true,
        "strict": true,
        "noEmit": true,
        "baseUrl": ".",
        "paths": {
            "~/*": ["./*"],
            "@/*": ["./*"]
        },
        "types": ["@types/node", "@nuxt/types"]
    },
    "exclude": ["node_modules"]
}

To make pagination working you will also need to install @types/mongoose-paginate-v2


The above solution should also deal with problems related to hot reloading with Nuxt (ServerMiddleware errors) and pagination plugin registration.

Solution 22 - node.js

The schema definition should be unique for a collection, it should not be more then one schema for a collection.

Solution 23 - node.js

If you want to overwrite the existing class for different collection using typescript
then you have to inherit the existing class from different class.

export class User extends Typegoose{
  @prop
  username?:string
  password?:string
}


export class newUser extends User{
    constructor() {
        super();
    }
}

export const UserModel = new User ().getModelForClass(User , { schemaOptions: { collection: "collection1" } });

export const newUserModel = new newUser ().getModelForClass(newUser , { schemaOptions: { collection: "collection2" } });

Solution 24 - node.js

I had the same problem, reason was I defined schema an model in a JS function, they should be defined globally in a node module, not in a function.

Solution 25 - node.js

just export like this exports.User = mongoose.models.User || mongoose.model('User', userSchema);

Solution 26 - node.js

ther are so many good answer but for checking we can do easier job. i mean in most popular answer there is check.js ,our guy made it so much complicated ,i suggest:

function connectToDB() {
  if (mongoose.connection.readyState === 1) {
    console.log("already connected");
    return;
  }
  mongoose.connect(
    process.env.MONGODB_URL,
    {
      useCreateIndex: true,
      useFindAndModify: false,
      useNewUrlParser: true,
      useUnifiedTopology: true,
    },
    (err) => {
      if (err) throw err;
      console.log("DB connected");
    },
  );
}

readyState== 1 means connected
so does not try to connect again
so you won't get the error
i think it because of connecting while it is connected
it is another way of connecting to db

Solution 27 - node.js

I faced this issue using Next.js and TypeScript. The top answers made it such that typings would not work.

This is what works for me:

const { Schema } = mongoose

export interface IUser {
  name: string
  email: string
}

const UserSchema = new Schema<IUser>({
  name: { type: String, required: true },
  email: { type: String, required: true },
})

const UserModel = () => mongoose.model<IUser>('User', UserSchema)

export default (mongoose.models.User || UserModel()) as ReturnType<
  typeof UserModel
>

Solution 28 - node.js

Adding this line will 100% solve your error.

mongoose.models = {}

Solution 29 - node.js

Make sure you are not using the same model name for two different schemas.

Example:

// course model
const mongoose = require("mongoose");
const courseSchema = new mongoose.Schema({
    course: {
        type: String,
        required: true,
    },
    course_category: {
        type: String,
        required: true,
    }
});
module.exports = mongoose.model("course", courseSchema);

// student model
const mongoose = require("mongoose");
const studentSchema = new mongoose.Schema({
    first_name: {
        type: String,
        required: true,
    },
    last_name: {
        type: String,
        required: true,
    }
});
module.exports = mongoose.model("course", studentSchema);

Solution 30 - node.js

is because your schema is already, validate before create new schema.

var mongoose = require('mongoose');
module.exports = function () {
var db = require("../libs/db-connection")();
//schema de mongoose
var Schema = require("mongoose").Schema;

var Task = Schema({
    field1: String,
    field2: String,
    field3: Number,
    field4: Boolean,
    field5: Date
})

if(mongoose.models && mongoose.models.tasks) return mongoose.models.tasks;

return mongoose.model('tasks', Task);

Solution 31 - node.js

You can easily solve this by doing

delete mongoose.connection.models['users'];
const usersSchema = mongoose.Schema({...});
export default mongoose.model('users', usersSchema);

Solution 32 - node.js

I have a situation where I have to create the model dynamically with each request and because of that I received this error, however, what I used to fix it is using deleteModel method like the following:

var contentType = 'Product'

var contentSchema = new mongoose.Schema(schema, virtuals);
      
var model = mongoose.model(contentType, contentSchema);
      
mongoose.deleteModel(contentType);

I hope this could help anybody.

Solution 33 - node.js

The reason of this issue is: 

you given the model name "users" in the line 
<<<var user = mongoose.model('users' {>>> in check.js file

and again the same model name you are giving in the insert file
<<< var user = mongoose.model('users',{ >>> in insert.js

This "users" name shouldn't be same when you declare a model that should be different 
in a same project.

Solution 34 - node.js

For all people ending here because of a codebase with a mix of Typegoose and Mongoose :

Create a db connection for each one :

Mongoose :

module.exports = db_mongoose.model("Car", CarSchema);

Typegoose :

db_typegoose.model("Car", CarModel.schema, "cars");

Solution 35 - node.js

I just have a mistake copy pasting. In one line I had same name that in other model (Ad model):

const Admin = mongoose.model('Ad', adminSchema);

Correct is:

const Admin = mongoose.model('Admin', adminSchema);

By the way, if someone have "auto-save", and use index for queries like:

**adSchema**.index({title:"text", description:"text", phone:"text", reference:"text"})

It has to delete index, and rewrite for correct model:

**adminSchema**.index({title:"text", description:"text", phone:"text", reference:"text"})

Solution 36 - node.js

Since this issue happened because calling model another time. Work around to this issue by wrapping your model code in try catch block. typescript code is like this -

         Import {Schema, model} from 'mongoose';
         export function user(){
              try{
                   return model('user', new Schema ({
                            FirstName: String,
                            Last name: String
                     }));
              }
             catch{
                   return model('user');
              }
         }

Similarly you can write code in js too.

Solution 37 - node.js

my mistake I use same name "Users" in others modals



const ProductSchema = new mongoose.Schema({
    title: { type: String, required: true, unique: true },
    desc: { type: String, required: true },
    img: { type: String, required: true },
    categorires: { type: Array },
    size: { type: String },
    color: { type: String },
    price: { type: Number, required: true },
},
    { timestamps: true }
);

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



*** Edit this line by me work look in your madels ***


module.exports = mongoose.model("Product", ProductSchema)

Solution 38 - node.js

If you are using Serverless offline one of these should do the trick

--skipCacheInvalidation

or

--useSeparateProcesses

especially this current one

--useChildProcesses

Solution 39 - node.js

You are using mongoose.model with the same variable name "user" in check.js and insert.js.

Solution 40 - node.js

If you are working with expressjs, you may need to move your model definition outside app.get() so it's only called once when the script is instantiated.

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
QuestionAnathema.ImbuedView Question on Stackoverflow
Solution 1 - node.jsjonnieView Answer on Stackoverflow
Solution 2 - node.jsthtsigmaView Answer on Stackoverflow
Solution 3 - node.jsZephDaviesView Answer on Stackoverflow
Solution 4 - node.jsBJ AndersonView Answer on Stackoverflow
Solution 5 - node.jsJulianView Answer on Stackoverflow
Solution 6 - node.jsmunyahView Answer on Stackoverflow
Solution 7 - node.jsJames HarringtonView Answer on Stackoverflow
Solution 8 - node.jsToufiqView Answer on Stackoverflow
Solution 9 - node.jsip192View Answer on Stackoverflow
Solution 10 - node.jsAlpha BAView Answer on Stackoverflow
Solution 11 - node.jsNone of your Beez WaxView Answer on Stackoverflow
Solution 12 - node.jsJustin HerreraView Answer on Stackoverflow
Solution 13 - node.jsRishabhView Answer on Stackoverflow
Solution 14 - node.jsRohit Reddy AbbadiView Answer on Stackoverflow
Solution 15 - node.jsMike KView Answer on Stackoverflow
Solution 16 - node.jsTimView Answer on Stackoverflow
Solution 17 - node.jsuser10261767View Answer on Stackoverflow
Solution 18 - node.jsJackView Answer on Stackoverflow
Solution 19 - node.jsDevMayukhView Answer on Stackoverflow
Solution 20 - node.jsABHIJEET KHIREView Answer on Stackoverflow
Solution 21 - node.jsJakub A SuplickiView Answer on Stackoverflow
Solution 22 - node.jsKARTHIKEYAN.AView Answer on Stackoverflow
Solution 23 - node.jsRohit JangidView Answer on Stackoverflow
Solution 24 - node.jsBulent BalciView Answer on Stackoverflow
Solution 25 - node.jsKhan Abu TalhaView Answer on Stackoverflow
Solution 26 - node.jsafshar003View Answer on Stackoverflow
Solution 27 - node.jsMansView Answer on Stackoverflow
Solution 28 - node.jsPunit KashyapView Answer on Stackoverflow
Solution 29 - node.jsAnkrah SolomonView Answer on Stackoverflow
Solution 30 - node.jsDiego Santa Cruz MendezúView Answer on Stackoverflow
Solution 31 - node.jsShyamView Answer on Stackoverflow
Solution 32 - node.jsEngr.MTHView Answer on Stackoverflow
Solution 33 - node.jsRohit JangidView Answer on Stackoverflow
Solution 34 - node.jsLucasBordeauView Answer on Stackoverflow
Solution 35 - node.jstitoihView Answer on Stackoverflow
Solution 36 - node.jsAKPView Answer on Stackoverflow
Solution 37 - node.jsPrashant ChouhanView Answer on Stackoverflow
Solution 38 - node.jsEdio PauloView Answer on Stackoverflow
Solution 39 - node.jsDavid KhanView Answer on Stackoverflow
Solution 40 - node.jsElesin Olalekan FuadView Answer on Stackoverflow