When you create a ReferenceField with an abstract class as an argument, it checks for the id_field in the meta dictionary of the abstract class itself, not the inherited class.
For example:
class A(Document):
val1 = StringField()
meta = {
"abstract": True
}
class B(A):
val2 = StringField()
class C(Document):
val3 = ReferenceField(A)
Trying to save an instance of C with an instance of B as val3 will raise a KeyError exception on line 945 of mongoengine/fields.py.