.NET Sporadic FormatException: Cannot deserialize a 'String' from BsonType 'ObjectId'

Since upgrading to .net 8 from .net 6 we are getting very unusual and sporadic behaviour from MongoDB (driver?). Every couple of days (sometimes weeks) the driver would throw the following exception during data read:

System.FormatException: An error occurred while deserializing the Id property of class X : Cannot deserialize a 'String' from BsonType 'ObjectId'.

Where X is a root class for 2 derived classes A & B.

public class X
{
    // MongoDB ObjectId
    public string Id { get; set; }

    // Other common properties...
}

public class A : X 
{
     // Stuff... but without ID (it is inherited from X)
}

public class B : X 
{
     // Stuff... but without ID (it is inherited from X)
}

This exception would continue to be thrown until the app is restarted which makes it work again for a couple of days.

MongoDB.Driver version is 3.4.0, server version is 4.2.8.

  • We are mapping our classes generically (no attributed whatsoever) before the connection is used.
  • ClassMap is registered in a static constructor.
  • Documents are only inserted in an X collection. A or B is queried using OfType on the X collection.
  • Inserted documents have the correct discriminator _t: [ X, A (or B) ] meaning it’s an array. I followed this web guide for polymorphism in MongoDB
  • TDocument can either be an X, A or B.
  • Our Mongo wrapper is a singleton.
                BsonSerializer.TryRegisterSerializer(new GuidSerializer(GuidRepresentation.CSharpLegacy));

                RegisterClassMap(typeof(TDocument), "Id");

                // not ideal -- I know
                var derivedTypes = AppDomain.CurrentDomain.GetAssemblies()
                    .SelectMany(assembly => assembly.GetLoadableTypes())
                    .Where(type => type is not null && !type.IsAbstract && type.IsSubclassOf(typeof(TDocument)));

                foreach (var derivedType in derivedTypes)
                {
                    RegisterClassMap(derivedType, "Id");
                }

                ConventionRegistry.Register(
                    "DocumentStorage.IgnoreExtraElements",
                    new ConventionPack() { new IgnoreExtraElementsConvention(true) },
                    type => true
                );
                ConventionRegistry.Register(
                    "DocumentStorage.IgnoreNull",
                    new ConventionPack { new IgnoreIfNullConvention(true) },
                    type => true
                );
            }

        private static void RegisterClassMap(Type classType, string idPropertyName)
        {
            if (classType.BaseType != typeof(object) && !BsonClassMap.IsClassMapRegistered(classType.BaseType))
                RegisterClassMap(classType.BaseType, idPropertyName);
            else if (classType is null || classType == typeof(object))
                return;

            if (!BsonClassMap.IsClassMapRegistered(classType))
            {
                var baseMap = BsonClassMap.IsClassMapRegistered(classType.BaseType)
                    ? BsonClassMap.LookupClassMap(classType.BaseType)
                    : null;

                var classMap = new BsonClassMap(classType, baseMap);

                classMap.AutoMap();
                classMap.SetIgnoreExtraElements(true);

                if (classMap.BaseClassMap?.IdMemberMap is null)
                {
                    classMap.SetIsRootClass(true);

                    classMap.MapIdProperty(idPropertyName)
                        .SetSerializer(new StringSerializer(BsonType.ObjectId))
                        .SetIdGenerator(StringObjectIdGenerator.Instance)
                        .SetIgnoreIfNull(false)
                        .SetIgnoreIfDefault(true);
                }

                classMap.Freeze();
                BsonClassMap.RegisterClassMap(classMap);
            }
        }

Please let me know if you need more info.

Sorry I don’t know how to edit the question, please find more information here: https://stackoverflow.com/questions/79700578/net-sporadic-formatexception-cannot-deserialize-a-string-from-bsontype-obje