- Error code
- 85
- Code name
IndexOptionsConflict- Product
- MongoDB
- Versions
- MongoDB 7.0 and 8.0 (wordings checked against the 8.0 source)
- Category
- Indexes & Collections
- Last reviewed
- 24 October 2026
On this page
What it means
Error 85 (IndexOptionsConflict) means createIndex asked for an index that MongoDB considers the same as an existing one but with other options or another name; its sibling 86 (IndexKeySpecsConflict) means the name is already used by a different index. MongoDB never changes an existing index in place.
When you call createIndex, MongoDB compares the request with the existing indexes. It treats a few properties as defining the index: the key pattern, unique, sparse, the collation, partialFilterExpression and a wildcard projection. Everything else, such as expireAfterSeconds, hidden or text index weights, is an option of that index. The documentation puts it plainly: with the exception of collation, if you create an index again with different options, MongoDB will not change the options nor recreate the index. The message shows both definitions (Requested index and existing index), so compare them field by field.
85 or 86: which one did you get?
85 IndexOptionsConflict: the defining properties match an existing index, but the options or the name differ. Typical case: changing a TTL from 3600 to 86400 seconds in code. If the requested index is fully identical but has a different name, the message is Index already exists with a different name. 86 IndexKeySpecsConflict: an index with the requested name exists but is a different index (another key pattern, or a different defining property). Because default names are built only from the fields and directions (email_1), adding unique: true to an existing { email: 1 } index definition without changing its name produces 86, not 85, as the message itself warns ("When index names are not specified, they are auto generated and can cause conflicts").
Both errors are common with ODMs and frameworks that create indexes at start-up from model definitions: the model changes, the old index is still on the server, and the next start-up fails. The fix depends on what changed: some options can be changed in place with collMod; others need the old index dropped and the new one built.
Common causes
- A TTL value (expireAfterSeconds) changed in the code or model while the index with the old value still exists (85).
- The same index requested under a new custom name, or with hidden or another option added (85).
- unique, sparse, a partial filter or a collation added to an index definition that keeps its auto-generated name (86).
- A key pattern changed (for example a compound index gains a field) while an explicit name is reused (86).
- Two services or ODM models define the same index differently and both create indexes at start-up.
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.
Show the existing index definitions
db.sessions.getIndexes() Every index with its name, key and options. Find the one named in existing index and compare it with the requested definition in the message.
Is the existing index in use?
db.sessions.aggregate([ { $indexStats: {} }, { $project: { name: 1, "accesses.ops": 1, "accesses.since": 1 } } ]) How often each index has been used since the server started. Use this before deciding to drop and rebuild an index that queries depend on.
Would the index be unique without errors?
db.users.aggregate([
{ $group: { _id: "$email", n: { $sum: 1 } } },
{ $match: { n: { $gt: 1 } } },
{ $limit: 10 }
]) Values that occur more than once. If any are listed, making the index unique will fail with E11000 until the duplicates are resolved.
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.
Change TTL or visibility in place with collMod (85)
Changes schemacollMod can change expireAfterSeconds and hidden on an existing index without rebuilding it. Then update the model so it requests the same values.
db.runCommand({
collMod: "sessions",
index: { keyPattern: { created_at: 1 }, expireAfterSeconds: 86400 }
})
Convert an existing index to unique with collMod (86)
Changes schemaThe documented conversion runs in steps: prepareUnique: true stops new duplicates, a dry run lists existing violations, then unique: true converts the index.
db.runCommand({ collMod: "users", index: { keyPattern: { email: 1 }, prepareUnique: true } })
db.runCommand({ collMod: "users", index: { keyPattern: { email: 1 }, unique: true }, dryRun: true })
db.runCommand({ collMod: "users", index: { keyPattern: { email: 1 }, unique: true } })
Give a genuinely different index its own name (86)
Changes schemaWhen both indexes should exist (for example the same keys with a different collation), name the new one explicitly so it does not collide with the auto-generated name.
db.users.createIndex(
{ email: 1 },
{ name: "email_ci", collation: { locale: "en", strength: 2 } }
)
Drop the old index and create the new definition
Changes schemaFor changes collMod cannot make, such as a new partial filter or key pattern, replace the index.
Caution: Between the drop and the end of the new build, queries lose that index and a unique constraint is not enforced. Check $indexStats first, consider building the new index under another name before dropping the old one, and do it in a quiet period.
db.orders.dropIndex("status_1")
db.orders.createIndex({ status: 1 }, { partialFilterExpression: { status: { $ne: "archived" } } })
Examples
Changing a TTL by calling createIndex again (85)
Not reproduced here: no MongoDB server is installed for this site. The text is built in MongoDB 8.0's index_catalog_impl.cpp; the two index documents are the server's view of each definition, and their exact field order here is illustrative.
db.sessions.createIndex({ created_at: 1 }, { expireAfterSeconds: 3600 })
// later, the model is changed to one day
db.sessions.createIndex({ created_at: 1 }, { expireAfterSeconds: 86400 })
MongoServerError: An equivalent index already exists with the same name but different options. Requested index: { v: 2, key: { created_at: 1 }, name: "created_at_1", expireAfterSeconds: 86400 }, existing index: { v: 2, key: { created_at: 1 }, name: "created_at_1", expireAfterSeconds: 3600 }
The same index under a new name (85)
Not reproduced here: no MongoDB server is installed for this site. The text is the one MongoDB 8.0's index_catalog_impl.cpp returns when the requested index is identical to an existing one apart from its name.
db.products.createIndex({ sku: 1 }) // name sku_1
db.products.createIndex({ sku: 1 }, { name: "sku_idx" })
MongoServerError: Index already exists with a different name: sku_1
Adding unique: true under the default name (86)
Not reproduced here: no MongoDB server is installed for this site. This is error 86 (IndexKeySpecsConflict): compareIndexOptions() in MongoDB 8.0 treats a different unique setting as a different index, and the name email_1 is already taken. The message text is from index_catalog_impl.cpp; the index documents are illustrative.
db.users.createIndex({ email: 1 }) // name email_1
db.users.createIndex({ email: 1 }, { unique: true }) // also named email_1
MongoServerError: An existing index has the same name as the requested index. When index names are not specified, they are auto generated and can cause conflicts. Please refer to our documentation. Requested index: { v: 2, unique: true, key: { email: 1 }, name: "email_1" }, existing index: { v: 2, key: { email: 1 }, name: "email_1" }
How to prevent it
Give important indexes explicit, descriptive names, and manage index changes in migrations rather than only through ODM auto-indexing at start-up.
When a model's index definition changes, ship the matching collMod or drop-and-create step with it, and compare getIndexes() with the model in each environment.
Common questions
How do I change expireAfterSeconds on an existing TTL index?
Use collMod with index: { keyPattern (or name), expireAfterSeconds }. Calling createIndex again with the new value fails with 85.
What is the difference between IndexOptionsConflict (85) and IndexKeySpecsConflict (86)?
85: the index is the same in key and defining properties but the options or name differ. 86: the requested name already belongs to a different index, for example after adding unique: true under the default name.
Why does Mongoose or my framework fail with this at start-up?
It creates indexes from the model, and the model no longer matches the index already on the server. Change the existing index with collMod, or drop and recreate it, then restart.
Learn more on CodeWithSQL
Official documentation
- db.collection.createIndex() (behaviour with existing indexes)
- collMod (change TTL, hidden, unique)
- Convert an existing index to a unique index
- MongoDB error codes (85, 86)
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.