This Mongoose error occurs when trying to register a model with the same name multiple times. It commonly happens in development environments with hot-reloading, serverless functions, or test suites that re-import model files.
This error is thrown by Mongoose (the MongoDB ODM) when you attempt to compile a model that has already been registered in the Mongoose instance. Mongoose maintains a global registry of all compiled models in `mongoose.models`, and once a model is compiled with a specific name, it cannot be overwritten without clearing the registry first. The error typically occurs because Mongoose is designed to prevent accidental model redefinition, which could lead to inconsistent schema definitions and unpredictable behavior. When your application tries to call `mongoose.model('User', userSchema)` twice, Mongoose detects the duplicate registration and throws this error to prevent conflicts. This is particularly common in Next.js API routes (which are deployed as serverless functions), development environments with hot module replacement (HMR), test suites that reload models before each test, and applications that import model files multiple times through different paths.
The safest solution is to check if the model already exists before creating it. Replace your model export with:
// models/User.js
const mongoose = require('mongoose');
const userSchema = new mongoose.Schema({
name: String,
email: String,
// ... other fields
});
// Check if model exists, otherwise create it
module.exports = mongoose.models.User || mongoose.model('User', userSchema);For TypeScript/ES modules:
// models/User.ts
import mongoose from 'mongoose';
const userSchema = new mongoose.Schema({
name: String,
email: String,
});
export default mongoose.models.User || mongoose.model('User', userSchema);This pattern checks mongoose.models.User first and only creates the model if it doesn't exist.
Make sure each model is defined and exported in exactly one file. Avoid duplicating model definitions across multiple files.
Good structure:
models/
├── User.js
├── Post.js
└── Comment.jsImport models consistently:
// Always import from the same location
const User = require('./models/User');
const Post = require('./models/Post');Node.js caches required modules, so importing the same file multiple times will return the cached export.
If you're getting this error in tests, avoid re-importing models in test hooks. Instead, import once at the top of the test file:
Before (causes error):
describe('User tests', () => {
let User;
beforeEach(() => {
// DON'T: This re-imports and tries to recompile the model
User = require('../models/User');
});
});After (fixed):
const User = require('../models/User'); // Import once at top
describe('User tests', () => {
beforeEach(async () => {
// Just clear data, don't re-import model
await User.deleteMany({});
});
});If you need to completely reset Mongoose between test suites, properly disconnect and clear models:
// test/setup.js or afterAll hook
afterAll(async () => {
// Clear all models from Mongoose registry
mongoose.connection.models = {};
// Close connection
await mongoose.disconnect();
});Or use Mongoose's deleteModel() method:
// Clear specific model
mongoose.deleteModel('User');
// Then you can safely recompile
const User = mongoose.model('User', userSchema);For Next.js applications: This error is extremely common in Next.js API routes because each API route is treated as a serverless function that may be reloaded during development. Always use the conditional export pattern (mongoose.models.ModelName || mongoose.model(...)) in Next.js projects.
Using separate connections: If you genuinely need multiple model registrations (rare), create separate Mongoose connections:
const conn1 = mongoose.createConnection('mongodb://localhost/db1');
const conn2 = mongoose.createConnection('mongodb://localhost/db2');
const User1 = conn1.model('User', userSchema);
const User2 = conn2.model('User', userSchema); // Different connection, no conflictTypeScript with Typegoose: When using Typegoose, use getModelForClass() with the conditional pattern:
import { getModelForClass } from '@typegoose/typegoose';
export const UserModel = mongoose.models.User || getModelForClass(User);Development vs Production: This error is more common in development due to hot-reloading. In production, models are typically loaded once during application startup, so the issue rarely occurs. However, serverless environments can trigger the same behavior in production if not handled correctly.
StaleShardVersion: shard version mismatch
How to fix "StaleShardVersion: shard version mismatch" in MongoDB
MongoOperationTimeoutError: Operation timed out
How to fix "MongoOperationTimeoutError: Operation timed out" in MongoDB
MongoServerError: PlanExecutor error during aggregation :: caused by :: Sort exceeded memory limit of 104857600 bytes, but did not opt in to external sorting. Aborting operation.
How to fix "QueryExceededMemoryLimitNoDiskUseAllowed" in MongoDB
MissingSchemaError: Schema hasn't been registered for model
How to fix "MissingSchemaError: Schema hasn't been registered for model" in MongoDB/Mongoose
CastError: Cast to ObjectId failed for value "abc123" at path "_id"
How to fix "CastError: Cast to ObjectId failed" in MongoDB