Sling Academy
Home/Node.js/Fix: Cannot overwrite model once compiled in Mongoose

Fix: Cannot overwrite model once compiled in Mongoose

Last updated: December 30, 2023

The Problem

The “Cannot overwrite model once compiled” error in Mongoose occurs, commonly due to attempting to recompile a model using the same schema with the same name, or requiring a module that defines a model multiple times. This leads to Mongoose throwing an error to prevent multiple instances of the same model from conflicting with each other.

Error Prevention & Solution

To prevent this error, you should ensure that models are compiled just once in your application and then shared wherever needed. Utilizing a mongoose model registry or structuring your app so that each model is defined in its own module, and requiring the module rather than the model directly, can be good practices.

Solving the Issue with Singleton Design Pattern

One of the conventional methods to solve this problem is implementing a Singleton pattern for requiring Mongoose models. Instead of calling mongoose.model() to compile the model each time, you call a function that checks if the model has already been compiled and, if so, returns the existing model. Here is an example of how to implement a Singleton pattern for your Mongoose models:

import mongoose from 'mongoose';
let userModel;
export const getUserModel = () => {
  if (!userModel) {
    const userSchema = new mongoose.Schema({
      username: String,
      password: String
    });
    userModel = mongoose.model('User', userSchema);
  }
  return userModel;
};

Refactoring to Use Module Caching

Node.js naturally supports module caching. If you define a model in one file and then require that file elsewhere, Node.js will cache the exported value after the first time it is loaded. Accordingly, all subsequent requires will return the already compiled model, thus preventing our error. Structure your model in such a way that it takes advantage of this.

// user.model.js
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
  username: String,
  password: String
});
const User = mongoose.model('User', userSchema);
export default User;

// otherfile.js
import User from './user.model';
// Use User model directly

Using Mongoose Connection Instance

Another method is to access models via the connected Mongoose instance. Since model names are unique per connection, attempting to obtain the model from the connection can help circumventing overwriting issues. An example of using the connection object to define or retrieve a model:

import mongoose from 'mongoose';
const connection = mongoose.createConnection(myDbUri);

const User = connection.models.User || connection.model('User', new mongoose.Schema({
  username: String,
  password: String
}));

Note that as per Node.js and JavaScript/TypeScript’s latest syntax, we are making use of ES modules, Promises with async/await, and arrow functions. This ensures our code is modern and consistent with current best practices.

Next Article: Mongoose: How to set expire TTL for a document

Previous Article: How to create auto-incrementing field in Mongoose

Series: Mongoose.js Tutorials

Node.js

You May Also Like

  • NestJS: How to create cursor-based pagination (2 examples)
  • Cursor-Based Pagination in SequelizeJS: Practical Examples
  • MongooseJS: Cursor-Based Pagination Examples
  • Node.js: How to get location from IP address (3 approaches)
  • SequelizeJS: How to reset auto-increment ID after deleting records
  • SequelizeJS: Grouping Results by Multiple Columns
  • NestJS: Using Faker.js to populate database (for testing)
  • NodeJS: Search and download images by keyword from Unsplash API
  • NestJS: Generate N random users using Faker.js
  • Sequelize Upsert: How to insert or update a record in one query
  • NodeJS: Declaring types when using dotenv with TypeScript
  • Using ExpressJS and Multer with TypeScript
  • NodeJS: Link to static assets (JS, CSS) in Pug templates
  • NodeJS: How to use mixins in Pug templates
  • NodeJS: Displaying images and links in Pug templates
  • ExpressJS + Pug: How to use loops to render array data
  • ExpressJS: Using MORGAN to Log HTTP Requests
  • NodeJS: Using express-fileupload to simply upload files
  • ExpressJS: How to render JSON in Pug templates