From 64a8c0bed9911140a319978c4c9ad2354fb388eb Mon Sep 17 00:00:00 2001 From: Fhatuwani Sikhwari Date: Fri, 5 Jun 2026 11:24:13 +0200 Subject: [PATCH] fix: map invalid mongo hint to invalid query error --- spec/ParseQuery.hint.spec.js | 18 +++++++++++++++ .../Storage/Mongo/MongoStorageAdapter.js | 22 +++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/spec/ParseQuery.hint.spec.js b/spec/ParseQuery.hint.spec.js index 2f61f658db..cb1046addb 100644 --- a/spec/ParseQuery.hint.spec.js +++ b/spec/ParseQuery.hint.spec.js @@ -153,6 +153,24 @@ describe_only_db('mongo')('Parse.Query hint', () => { expect(explain.queryPlanner.winningPlan.inputStage.inputStage.indexName).toBe('_id_'); }); + it('query find with invalid hint returns invalid query error', async () => { + const object = new TestObject(); + await object.save(); + + const query = new Parse.Query(TestObject); + query.equalTo('objectId', object.id); + query.hint('missing_index'); + + try { + await query.find({ useMasterKey: true }); + fail('Expected query.find to fail'); + } catch (error) { + expect(error.code).toBe(Parse.Error.INVALID_QUERY); + expect(error.message.toLowerCase()).toContain('hint'); + expect(error.code).not.toBe(Parse.Error.INTERNAL_SERVER_ERROR); + } + }); + it_only_mongodb_version('>=7')('query aggregate with hint (rest)', async () => { const object = new TestObject({ foo: 'bar' }); await object.save(); diff --git a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js index 9c17b2a18b..ced9645242 100644 --- a/src/Adapters/Storage/Mongo/MongoStorageAdapter.js +++ b/src/Adapters/Storage/Mongo/MongoStorageAdapter.js @@ -58,6 +58,24 @@ function isTransientError(error) { return false; } +function isInvalidHintError(error) { + if (!error || typeof error.message !== 'string') { + return false; + } + + const message = error.message.toLowerCase(); + const hasHintContext = message.includes('hint'); + const hasIndexContext = + message.includes('index') || + message.includes('badvalue') || + error.code === 2 || + error.code === 27 || + error.codeName === 'BadValue' || + error.codeName === 'IndexNotFound'; + + return hasHintContext && hasIndexContext; +} + const storageAdapterAllCollections = mongoAdapter => { return mongoAdapter .connect() @@ -293,6 +311,10 @@ export class MongoStorageAdapter implements StorageAdapter { throw new Parse.Error(Parse.Error.INTERNAL_SERVER_ERROR, 'Database error'); } + if (isInvalidHintError(error)) { + throw new Parse.Error(Parse.Error.INVALID_QUERY, `Invalid hint: ${error.message}`); + } + throw error; }