From 59ab0bbbdeccdb125a31fd895040a943bcab1720 Mon Sep 17 00:00:00 2001 From: Daniel Date: Sun, 5 Jul 2026 00:44:55 +1000 Subject: [PATCH] fix: Server crashes on startup with cryptic error when a Mongo _SCHEMA field has a non-string type --- spec/MongoSchemaCollectionAdapter.spec.js | 25 +++++++++++++++++++ .../Storage/Mongo/MongoSchemaCollection.js | 11 ++++++-- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/spec/MongoSchemaCollectionAdapter.spec.js b/spec/MongoSchemaCollectionAdapter.spec.js index 8e376b9d1d..aae869a5c4 100644 --- a/spec/MongoSchemaCollectionAdapter.spec.js +++ b/spec/MongoSchemaCollectionAdapter.spec.js @@ -2,6 +2,7 @@ const MongoSchemaCollection = require('../lib/Adapters/Storage/Mongo/MongoSchemaCollection') .default; +const Parse = require('parse/node'); describe('MongoSchemaCollection', () => { it('can transform legacy _client_permissions keys to parse format', done => { @@ -96,4 +97,28 @@ describe('MongoSchemaCollection', () => { }); done(); }); + + it('throws a clear error for a null field type instead of crashing (#9847)', () => { + expect(() => + MongoSchemaCollection._TESTmongoSchemaToParseSchema({ + _id: 'SomeClass', + goodField: 'string', + badField: null, + }) + ).toThrowMatching( + e => + e.code === Parse.Error.INCORRECT_TYPE && + e.message.includes('SomeClass') && + e.message.includes('badField') + ); + }); + + it('throws a clear error for a non-string object field type (#9847)', () => { + expect(() => + MongoSchemaCollection._TESTmongoSchemaToParseSchema({ + _id: 'SomeClass', + badField: { foo: 1 }, + }) + ).toThrowMatching(e => e.code === Parse.Error.INCORRECT_TYPE); + }); }); diff --git a/src/Adapters/Storage/Mongo/MongoSchemaCollection.js b/src/Adapters/Storage/Mongo/MongoSchemaCollection.js index 45b27f7516..66187531d1 100644 --- a/src/Adapters/Storage/Mongo/MongoSchemaCollection.js +++ b/src/Adapters/Storage/Mongo/MongoSchemaCollection.js @@ -1,7 +1,14 @@ import MongoCollection from './MongoCollection'; import Parse from 'parse/node'; -function mongoFieldToParseSchemaField(type) { +function mongoFieldToParseSchemaField(type, fieldName, className) { + if (typeof type !== 'string') { + throw new Parse.Error( + Parse.Error.INCORRECT_TYPE, + `Invalid schema for class '${className}': field '${fieldName}' has an invalid type ` + + `(${type === null ? 'null' : typeof type}). Expected a string type descriptor.` + ); + } if (type[0] === '*') { return { type: 'Pointer', @@ -43,7 +50,7 @@ const nonFieldSchemaKeys = ['_id', '_metadata', '_client_permissions']; function mongoSchemaFieldsToParseSchemaFields(schema) { var fieldNames = Object.keys(schema).filter(key => nonFieldSchemaKeys.indexOf(key) === -1); var response = fieldNames.reduce((obj, fieldName) => { - obj[fieldName] = mongoFieldToParseSchemaField(schema[fieldName]); + obj[fieldName] = mongoFieldToParseSchemaField(schema[fieldName], fieldName, schema._id); if ( schema._metadata && schema._metadata.fields_options &&