Fortunately, the error message is clear enough for understanding the problem root cause. You have some documents in users collection that were saved with different schema, where referrals was just a string, not an array of ObjectId. And now, when you try to deserialize those objects, you get fair error that String could not be deserialized to List<ObjectId?>.
If currently your database contains just some test data, you could clear the collection and start from the scratch. As far as documents with old schema will not be saved anymore, you will not face the error again.
If you have to preserve existing data, you should manually delete documents with old schema or migrate their data to new schema, so that these documents could be successfully deserialized.
If however you can't delete data with outdated schema, you should implement custom serializer so that reading the data from DB could succeed. Here is a sample serializer that ignores String values during deserialization:
public class FixingReferralsSerializer : EnumerableSerializerBase<List<ObjectId?>>
{
public override List<ObjectId?> Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
if (context.Reader.CurrentBsonType == BsonType.String)
{
context.Reader.ReadString();
return null;
}
return base.Deserialize(context, args);
}
protected override void AddItem(object accumulator, object item)
{
((List<ObjectId?>)accumulator).Add((ObjectId?)item);
}
protected override object CreateAccumulator()
{
return new List<ObjectId?>();
}
protected override IEnumerable EnumerateItemsInSerializationOrder(List<ObjectId?> value)
{
return value;
}
protected override List<ObjectId?> FinalizeResult(object accumulator)
{
return (List<ObjectId?>)accumulator;
}
}
You could set this serializer for referrals field through BsonSerializer attribute:
[BsonIgnoreExtraElements]
public class User : Document
{
[BsonDefaultValue(null)]
[BsonSerializer(typeof(FixingReferralsSerializer))]
public List<ObjectId?> referrals { get; set; }
}
Serializer class would be much simpler if you could change the type of referrals field from List<ObjectId?> to Array<ObjectId?>. In this case you could base serializer implementation on ArraySerializer<T>:
public class FixingReferralsSerializer : ArraySerializer<ObjectId?>
{
public override ObjectId?[] Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
if (context.Reader.CurrentBsonType == BsonType.String)
{
context.Reader.ReadString();
return null;
}
return base.Deserialize(context, args);
}
}