parse-community / parse-community/parse-server
IndexKeySpecsConflict on _Idempotency TTL index prevents startup after Parse Server update (MongoDB 8.0)
Nobody has claimed this yet.
- Dominant language
- JavaScript
- Stars
- 21.4k
- Forks
- 4.8k
- Avg merge
- 7h 45m
- Merged PRs (30d)
- 11
Description
New Issue Checklist
- I am not disclosing a vulnerability.
- I am not just asking a question.
- I have searched through existing issues.
Issue Description
Parse Server fails to start with MongoServerError: IndexKeySpecsConflict (error code 86) on the _Idempotency collection's TTL index after updating Parse Server on an existing MongoDB 8.0 deployment. The error occurs on every restart and prevents the server from starting.
MongoDB 8.0 introduced an internal index property called enableOrderedIndex. Whether this property is included in the index specification depends on how the createIndex command is sent by the MongoDB Node.js driver. The previous Parse Server version used an older MongoDB driver that created the TTL index without enableOrderedIndex. The updated Parse Server (9.8.0) ships with MongoDB Node.js driver 7.1.0 (upgraded from 7.0.0 in PR #10087), which causes MongoDB 8.0 to add enableOrderedIndex: 1 to the new index specification.
At every startup, Parse Server calls ensureIndex on the _Idempotency collection to create the TTL index (in DatabaseController.performInitialization). This internally calls collection.createIndex() via MongoStorageAdapter.ensureIndex(). The new driver/request now includes enableOrderedIndex: 1, but the existing index (created by the previous Parse Server version with the older driver) does not have this property. MongoDB treats these as conflicting specifications for the same index name "ttl" and throws IndexKeySpecsConflict.
The .catch() handler in DatabaseController.js re-throws the error, which prevents Parse Server from starting. The error persists on every subsequent restart because the old index is never dropped or updated.
Relevant code paths:
src/Controllers/DatabaseController.js~line 1915: callsensureIndex('_Idempotency', ..., ['expire'], 'ttl', false, { ttl: 0 })and re-throws on errorsrc/Adapters/Storage/Mongo/MongoStorageAdapter.js~line 818:ensureIndex()callscollection._mongoCollection.createIndex()without handling error code 86
Steps to reproduce
- Run a previous version of Parse Server (e.g. < 9.4.1, with an older MongoDB Node.js driver) with
idempotencyOptionsenabled against MongoDB 8.0 — the_IdempotencyTTL index is created without theenableOrderedIndexproperty - Update Parse Server to 9.8.0 (alpha branch, which ships with MongoDB Node.js driver 7.1.0)
- Start Parse Server — it fails with
IndexKeySpecsConflict(error code 86) - Every subsequent restart fails with the same error
Note: This issue affects any deployment on MongoDB 8.0 where the TTL index was created by a previous Parse Server version using an older MongoDB Node.js driver. Fresh deployments (no pre-existing _Idempotency collection) are not affected.
Actual Outcome
Parse Server crashes on startup with the following error:
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, "key" : { "expire" : 1 }, "name" : "ttl", "sparse" : true, "expireAfterSeconds" : 0, "enableOrderedIndex" : 1 }
existing index: { "v" : 2, "key" : { "expire" : 1 }, "name" : "ttl", "sparse" : true, "expireAfterSeconds" : 0 }
The only difference between the two index specifications is the enableOrderedIndex: 1 field, which is automatically added by the MongoDB 8.0 server — it is not set by Parse Server or the MongoDB Node.js driver.
Expected Outcome
Parse Server should start successfully. The ensureIndex call should gracefully handle error code 86 (IndexKeySpecsConflict) when the existing index is functionally equivalent (same key, name, sparse, and TTL settings).
Possible fixes:
- In
MongoStorageAdapter.ensureIndex(), catch error code 86 and either ignore it (the index is functionally equivalent) or drop and recreate the index - In
DatabaseController.performInitialization, don't re-throw the error for the TTL index when the error code is 86 - Check if the index already exists before calling
createIndex
Workaround: Drop the index manually before starting Parse Server:
db._Idempotency.dropIndex("ttl")
Parse Server will recreate the index on startup with the enableOrderedIndex field included.
Environment
Server
- Parse Server version:
9.8.0 - Operating system:
Linux - Local or remote host (AWS, Azure, Google Cloud, Heroku, Digital Ocean, etc):
Azure
Database
- System (MongoDB or Postgres):
MongoDB - Database version:
8.0 - Local or remote host (MongoDB Atlas, mLab, AWS, Azure, Google Cloud, etc):
Azure
Client
- SDK (iOS, Android, JavaScript, PHP, Unity, etc):
N/A — server startup issue, no client involved - SDK version:
N/A
Logs
error: ParseServer failed to start 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, "key" : { "expire" : 1 }, "name" : "ttl", "sparse" : true, "expireAfterSeconds" : 0, "enableOrderedIndex" : 1 }, existing index: { "v" : 2, "key" : { "expire" : 1 }, "name" : "ttl", "sparse" : true, "expireAfterSeconds" : 0 }
at Connection.onMessage (...)
at MessageStream.<anonymous> (...)
at processTicksAndRejections (...)
at async DatabaseController.performInitialization (src/Controllers/DatabaseController.js)
at async ParseServer.start (src/ParseServer.js)
at async ParseServer.startApp (src/ParseServer.js)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with DatabaseController.performInitialization around the _Idempotency TTL ensureIndex call and MongoStorageAdapter.ensureIndex around createIndex. Reproduce the conflict on MongoDB 8.0 using an index created by an older Parse Server version, then verify that startup succeeds with the existing functionally equivalent index and that error handling does not hide other index failures.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- javascript, mongodb, nodejs
- Domain
- backend, database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 48/100