2

I am seeing some strange behavior where DescribeFieldResult.getReferenceTo returns only one type for the Lead.OwnerId field in some cases when invoked in a trigger context.

The code below displays OwnerId has 2 target types as expected when run in a unit test or Execute Anonymous. But when it is run in a trigger it only finds one type: User, but not Group.

DescribeSObjectResult leadDesc = Lead.sObjectType.getDescribe();
Map<String, sObjectField> leadFields = leadDesc.fields.getMap();
sObjectField lookupField = leadFields.get('OwnerId');
DescribeFieldResult lfDesc = lookupField.getDescribe();
List<SObjectType> refObjs = lfDesc.getReferenceTo();
System.debug(LoggingLevel.INFO, 'OwnerId has ' + refObjs.size() + ' target types');

To make it even more curious this happens when the trigger is invoked as a result of a manual edit of a record, but not when the trigger is invoked as part of a unit test.

I'm stumped -- any thoughts would be very welcome...

[Update]
Further testing in a clean test org shows that this happens only:

  • When the lead is updated from a list view or detail page
    • It works fine if the lead is updated from anonymous APEX, unit tests or batch APEX
  • In an insert or after update trigger
    • before update triggers work OK
    • after update also works if the trigger also handles the before update event (even if it does nothing)

Specifically the following trigger fails the assertion:

trigger TestTrigger on Lead (after update) {
    List<SObjectType> refObjs = Lead.OwnerId.getDescribe().getReferenceTo();
    System.assertEquals(2, refObjs.size());
}

But it works fine like this:

trigger TestTrigger on Lead (before update, after update) {
    if (Trigger.isBefore) return;
    List<SObjectType> refObjs = Lead.OwnerId.getDescribe().getReferenceTo();
    System.assertEquals(2, refObjs.size());
}

The same code fails for insert triggers in any combination of before or after

Last observation: the List<SObjectType> returned by DescribeFieldResult.getReferenceTo is actually modifiable, and explicitly adding the Group object in the before insert allows the after insert to go through:

trigger TestTrigger on Lead (before insert, after insert) {
    List<SObjectType> refObjs = Lead.OwnerId.getDescribe().getReferenceTo();
    if (Trigger.isBefore && (refObjs.size()<2)) {
        refObjs.add(Group.sObjectType);
        refObjs = Lead.OwnerId.getDescribe().getReferenceTo();
        System.debug(LoggingLevel.INFO, 'OwnerId now has ' + refObjs.size() + ' target types');
    }
    System.assertEquals(2, refObjs.size());
}

It looks an awful lot like a defect to me -- but if there is some setting that would avoid the behavior I would be happy to know about it...

  • If you invoke the trigger on the lead that has queue as an Owner, than it will display another result in trigger class. Are you sure you are retrieving sObject type from Lead (as a meta class) and not from the current lead_i sObject lead in the trigger? – Mariia Illarionova Jul 4 '19 at 6:43
  • @MariiaIllarionova thanks for the quick response, but I'm afraid I don't understand your question. The DescribeSObjectResult will (or at least should) be the same regardless of how it is obtained. And in any case I am sure that Lead.sObjectType refers to the Lead object, not an instance – Jelle van Geuns Jul 4 '19 at 6:57
  • I quess that happens in the trigger because actually you cannot assign the lead to a public group, only to queue, but queue is considered as User reference type in SF. – Mariia Illarionova Jul 4 '19 at 7:09
  • (1) does the running user have access to Lead queues in some use cases but not others (2) are classes and unit tests also at v46 (which is what exec anon is using at time of this OP) – cropredy Jul 4 '19 at 19:02
  • Hi @cropredy not sure what you mean by 'access to Lead queues' in point 1)? Is there a specific permission you were thinking of? I'm using the same user in both scenarios. And for point 2): yes, it's all v46 – Jelle van Geuns Jul 5 '19 at 7:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.