From 8cfd8ff2f484270c578d5c466bf9a568a8197e5f Mon Sep 17 00:00:00 2001 From: Rahul Lanjewar Date: Sun, 9 Nov 2025 02:07:59 +0530 Subject: [PATCH 1/5] feat: add information about, db collection and index name --- spec/schemas.spec.js | 1 + .../Storage/Mongo/MongoStorageAdapter.js | 27 +++++++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index 7891fa847e..6acadbb948 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -3835,6 +3835,7 @@ describe('schemas', () => { .then(done.fail) .catch(error => { expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE); + expect(error.message).toEqual('A duplicate value for a field with unique values was provided Duplicate index: code_1 on collection test_UniqueIndexClass in db parseServerMongoAdapterTestDatabase') done(); }); }); diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 481d5257d9..f8f133488a 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -26,6 +26,29 @@ const ReadPreference = mongodb.ReadPreference; const MongoSchemaCollectionName = '_SCHEMA'; + +// If we get a unique index error from mongo, try to parse it. If successful, return it. +const mongoUniqueIndexErrorFormatter = (message) => { + /** + * Sample error message that we are getting from mongo + * 'Plan executor error during findAndModify :: caused by :: E11000 duplicate key error collection: parseServerMongoAdapterTestDatabase.test_UniqueIndexClass index: code_1 dup key: { code: 2 }' + */ + const regex = /collection:\s*([\w]+)\.([\w]+)\s+index:\s*([\w_]+)/; + + const match = message.match(regex); + + if (match) { + const dbName = match[1]; + const collectionName = match[2]; + const indexName = match[3]; + // Adding extra starting space to make it more readable. + return ` Duplicate index: ${indexName} on collection ${collectionName} in db ${dbName}`; + } + + // Return nothing + return ''; +} + const storageAdapterAllCollections = mongoAdapter => { return mongoAdapter .connect() @@ -490,7 +513,7 @@ export class MongoStorageAdapter implements StorageAdapter { // Duplicate value const err = new Parse.Error( Parse.Error.DUPLICATE_VALUE, - 'A duplicate value for a field with unique values was provided' + `A duplicate value for a field with unique values was provided.${mongoUniqueIndexErrorFormatter(error.message)}` ); err.underlyingError = error; if (error.message) { @@ -575,7 +598,7 @@ export class MongoStorageAdapter implements StorageAdapter { if (error.code === 11000) { throw new Parse.Error( Parse.Error.DUPLICATE_VALUE, - 'A duplicate value for a field with unique values was provided' + `A duplicate value for a field with unique values was provided.${mongoUniqueIndexErrorFormatter(error.message)}` ); } throw error; From 17c89093570b80e5dd5f5a8643fbc25235957aeb Mon Sep 17 00:00:00 2001 From: Rahul Lanjewar Date: Sun, 9 Nov 2025 02:12:39 +0530 Subject: [PATCH 2/5] fix: minor --- spec/schemas.spec.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index 6acadbb948..618a8c547a 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -3835,7 +3835,7 @@ describe('schemas', () => { .then(done.fail) .catch(error => { expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE); - expect(error.message).toEqual('A duplicate value for a field with unique values was provided Duplicate index: code_1 on collection test_UniqueIndexClass in db parseServerMongoAdapterTestDatabase') + expect(error.message).toEqual('A duplicate value for a field with unique values was provided. Duplicate index: code_1 on collection test_UniqueIndexClass in db parseServerMongoAdapterTestDatabase') done(); }); }); From 0473c9046eb82675ae5c5fe7b4e0855fe4c78ae8 Mon Sep 17 00:00:00 2001 From: Rahul Lanjewar <63550998+RahulLanjewar93@users.noreply.github.com> Date: Sun, 9 Nov 2025 02:22:24 +0530 Subject: [PATCH 3/5] Apply suggestion from @RahulLanjewar93 Signed-off-by: Rahul Lanjewar <63550998+RahulLanjewar93@users.noreply.github.com> --- src/Adapters/Storage/Mongo/MongoStorageAdapter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index f8f133488a..8f674c21a2 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -33,7 +33,7 @@ const mongoUniqueIndexErrorFormatter = (message) => { * Sample error message that we are getting from mongo * 'Plan executor error during findAndModify :: caused by :: E11000 duplicate key error collection: parseServerMongoAdapterTestDatabase.test_UniqueIndexClass index: code_1 dup key: { code: 2 }' */ - const regex = /collection:\s*([\w]+)\.([\w]+)\s+index:\s*([\w_]+)/; + const regex = /collection:\s*([\w-]+)\.([\w-]+)\s+index:\s*([\w-]+)/; const match = message.match(regex); From 8a161df9ddbaa33a097e53733c1e7f260813e8e8 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Sun, 14 Dec 2025 16:16:34 +0100 Subject: [PATCH 4/5] fix --- spec/schemas.spec.js | 9 +++++- .../Storage/Mongo/MongoStorageAdapter.js | 30 +++---------------- 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index f9264733bf..f40f6b4114 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -3842,6 +3842,8 @@ describe('schemas', () => { }); it_id('cbd5d897-b938-43a4-8f5a-5d02dd2be9be')(it_exclude_dbs(['postgres']))('cannot update to duplicate value on unique index', done => { + const logger = require('../lib/logger').default; + const loggerErrorSpy = spyOn(logger, 'error').and.callThrough(); const index = { code: 1, }; @@ -3868,7 +3870,12 @@ describe('schemas', () => { .then(done.fail) .catch(error => { expect(error.code).toEqual(Parse.Error.DUPLICATE_VALUE); - expect(error.message).toEqual('A duplicate value for a field with unique values was provided. Duplicate index: code_1 on collection test_UniqueIndexClass in db parseServerMongoAdapterTestDatabase') + // Client should only see generic message (no schema info exposed) + expect(error.message).toEqual('A duplicate value for a field with unique values was provided'); + // Server logs should contain full MongoDB error message with detailed information + expect(loggerErrorSpy).toHaveBeenCalledWith('Duplicate key error:', jasmine.stringContaining('E11000 duplicate key error')); + expect(loggerErrorSpy).toHaveBeenCalledWith('Duplicate key error:', jasmine.stringContaining('test_UniqueIndexClass')); + expect(loggerErrorSpy).toHaveBeenCalledWith('Duplicate key error:', jasmine.stringContaining('code_1')); done(); }); }); diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 453ee43f3c..24b206aec9 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -27,29 +27,6 @@ const ReadPreference = mongodb.ReadPreference; const MongoSchemaCollectionName = '_SCHEMA'; - -// If we get a unique index error from mongo, try to parse it. If successful, return it. -const mongoUniqueIndexErrorFormatter = (message) => { - /** - * Sample error message that we are getting from mongo - * 'Plan executor error during findAndModify :: caused by :: E11000 duplicate key error collection: parseServerMongoAdapterTestDatabase.test_UniqueIndexClass index: code_1 dup key: { code: 2 }' - */ - const regex = /collection:\s*([\w-]+)\.([\w-]+)\s+index:\s*([\w-]+)/; - - const match = message.match(regex); - - if (match) { - const dbName = match[1]; - const collectionName = match[2]; - const indexName = match[3]; - // Adding extra starting space to make it more readable. - return ` Duplicate index: ${indexName} on collection ${collectionName} in db ${dbName}`; - } - - // Return nothing - return ''; -} - const storageAdapterAllCollections = mongoAdapter => { return mongoAdapter .connect() @@ -542,10 +519,10 @@ export class MongoStorageAdapter implements StorageAdapter { .then(() => ({ ops: [mongoObject] })) .catch(error => { if (error.code === 11000) { - // Duplicate value + logger.error('Duplicate key error:', error.message); const err = new Parse.Error( Parse.Error.DUPLICATE_VALUE, - `A duplicate value for a field with unique values was provided.${mongoUniqueIndexErrorFormatter(error.message)}` + 'A duplicate value for a field with unique values was provided' ); err.underlyingError = error; if (error.message) { @@ -628,9 +605,10 @@ export class MongoStorageAdapter implements StorageAdapter { .then(result => mongoObjectToParseObject(className, result, schema)) .catch(error => { if (error.code === 11000) { + logger.error('Duplicate key error:', error.message); throw new Parse.Error( Parse.Error.DUPLICATE_VALUE, - `A duplicate value for a field with unique values was provided.${mongoUniqueIndexErrorFormatter(error.message)}` + 'A duplicate value for a field with unique values was provided' ); } throw error; From 98050b40d59b053eb61df2001d83a438d08d78a5 Mon Sep 17 00:00:00 2001 From: Manuel Trezza <5673677+mtrezza@users.noreply.github.com> Date: Sun, 14 Dec 2025 16:30:22 +0100 Subject: [PATCH 5/5] spy --- spec/schemas.spec.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/spec/schemas.spec.js b/spec/schemas.spec.js index f40f6b4114..f9f29c733e 100644 --- a/spec/schemas.spec.js +++ b/spec/schemas.spec.js @@ -3842,8 +3842,7 @@ describe('schemas', () => { }); it_id('cbd5d897-b938-43a4-8f5a-5d02dd2be9be')(it_exclude_dbs(['postgres']))('cannot update to duplicate value on unique index', done => { - const logger = require('../lib/logger').default; - const loggerErrorSpy = spyOn(logger, 'error').and.callThrough(); + loggerErrorSpy.calls.reset(); const index = { code: 1, };