- Error code
- 11000
- Code name
DuplicateKey- Product
- MongoDB
- Versions
- MongoDB 4.4 to 8.0 (format checked against the 8.0 source)
- Category
- Writes & Validation
- Last reviewed
- 24 October 2026
On this page
What it means
Error 11000 (DuplicateKey) means a write would store a key that already exists in a unique index, such as _id or a unique email index, so MongoDB rejected that document.
Every collection has a unique index on _id, and you can create others with { unique: true }. When an insert, update or upsert would give a second document the same value for a unique index, MongoDB rejects the write with code 11000. The message gives the namespace (database.collection), the index name and the duplicate key: dup key: { email: "sara@example.com" }. The error document returned to drivers also includes keyPattern and keyValue, which are easier to read in code than the message text.
MongoDB documents a common surprise: a unique index on a single field treats a missing field as null, so a second document without that field is a duplicate too. Creating a unique index on a collection that already contains duplicates also fails with 11000, naming the first duplicate it finds.
Common causes
- The same document is inserted twice: a retried request or an import that runs again with explicit _id values.
- The application sends a value that already exists for a unique field, such as an email address or a username.
- Several documents have no value for a unique single-field index: the missing field counts as null, and null is allowed only once.
- Two upserts with the same filter run at the same moment and both try to insert.
- A unique index is created on a collection that already holds duplicate values.
Diagnose it
Read-only These mongosh commands only read data, indexes, statistics and server state (find, aggregate without $out or $merge, getIndexes, stats, currentOp, rs.status). They do not change data, users or settings, so they are safe to run first.
Which fields does the index cover?
db.users.getIndexes() Each index with its key and options. The one named in the message (for example email_1) shows unique: true; check whether it is partial (partialFilterExpression) or sparse, which changes which documents it covers.
Find the document that already holds the key
db.users.find({ email: "sara@example.com" }) // the dup key from the message The existing document. Decide whether to skip the new one, update the existing one or reject the request.
Find duplicates before creating a unique index
db.users.aggregate([
{ $group: { _id: "$email", copies: { $sum: 1 }, ids: { $push: "$_id" } } },
{ $match: { copies: { $gt: 1 } } },
{ $sort: { copies: -1 } }
]) Each value that appears more than once, with the _id values of the documents involved. A group whose _id is null collects the documents where the field is missing or null.
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Update the existing document instead (upsert)
Changes dataWhen a matching document should be updated rather than rejected, use an update with upsert: true and filter on the unique field. Two concurrent upserts with the same filter can still both try to insert, and one of them can then fail with 11000; retrying it finds the document that now exists and updates it.
db.users.updateOne(
{ email: "sara@example.com" },
{ $set: { name: "Sara Ahmed" } },
{ upsert: true }
)
Skip duplicates in a bulk insert
Changes dataWith ordered: false, insertMany carries on after a duplicate and reports every failed document in writeErrors, instead of stopping at the first one. Check the errors afterwards: only skip ones whose code is 11000.
db.users.insertMany(docs, { ordered: false })
Exclude documents without the field from the unique index
Changes schemaWhen the field is optional, a partial index applies uniqueness only to documents that have it, so documents without an email no longer collide as null.
Caution: An existing index with the same key must be dropped first (the old one cannot be changed in place), which leaves the field unprotected until the new index is built. Check the duplicates query above first, and do it in a maintenance window.
db.users.createIndex(
{ email: 1 },
{ unique: true, partialFilterExpression: { email: { $exists: true } } }
)
Examples
Inserting an email address that is already registered
Not reproduced here: no MongoDB server is installed for this site. The result shows the message format built by MongoDB 8.0's server code (buildDupKeyErrorStatus) as mongosh prints it, with this example's names filled in (database shop).
db.users.createIndex({ email: 1 }, { unique: true })
db.users.insertOne({ email: "sara@example.com", name: "Sara" })
db.users.insertOne({ email: "sara@example.com", name: "Sara B" })
MongoServerError: E11000 duplicate key error collection: shop.users index: email_1 dup key: { email: "sara@example.com" }
Two documents without the unique field
Not reproduced here: no MongoDB server is installed for this site. MongoDB's unique index documentation describes this behaviour (a missing field is stored as null in a unique single-field index); the result shows the documented message format with this example's names filled in.
db.users.createIndex({ email: 1 }, { unique: true })
db.users.insertOne({ name: "Ali" }) // no email: indexed as null
db.users.insertOne({ name: "Omar" }) // also null
MongoServerError: E11000 duplicate key error collection: shop.users index: email_1 dup key: { email: null }
How to prevent it
Use upserts for "create or update" actions, make imports idempotent, and keep unique indexes on fields that must be unique even when the application checks first. For optional unique fields, use a partial index from the start.
Handle code 11000 in your code (check the code, not the message text, and read keyValue) so a duplicate becomes a clear message such as "this email is already registered", and retry concurrent upserts that lose the race.
Common questions
How do I fix E11000 duplicate key error in MongoDB?
Read the index name and the dup key from the message, find the document that already has that value, then skip the new document, update the existing one with an upsert, or remove the duplicate data before creating a unique index.
Why do I get E11000 with dup key: { email: null }?
Several documents have no email field. A unique single-field index stores a missing field as null and allows null only once. Use a partial index that covers only documents where the field exists.
Can I ignore duplicate errors in insertMany?
Use ordered: false so the other documents are still inserted, then inspect writeErrors and treat only code 11000 as an expected duplicate; other errors still need handling.
Learn more on CodeWithSQL
Official documentation
- MongoDB error codes (11000 DuplicateKey)
- Unique indexes
- db.collection.insertOne() (write error example)
- Partial indexes
Last technically reviewed 24 October 2026; examples and diagnostics run on MongoDB 8.0 documentation and source (error_codes.yml r8.0.0); not run locally. Codes and code names are checked against MongoDB's error_codes.yml (8.0); no MongoDB server was available, so the examples were not run locally.