function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Ken Fitzpatrick 10Ken Fitzpatrick 10 

Why would the addition of System.Debug make the issue I was debugging go away?

So, I have a very strange issue. I have the following code:
private static List<Id> getCaseRecordTypes(String acctMgrType){
        List<Id> caseRecordTypeIds = new List<Id>(); //Id list to return
        //System.debug(LoggingLevel.ERROR, '*** Kentest --> ' + caseRecordTypeIds);
        Map<String, ID> caseTypes = ObjectHelper.GetRecordTypeIdsByDeveloperName(Case.SObjectType);
        
        String accountMgrTypeValue = acctMgrType + '_Case_Record_Types';
        Account_Manager_Assignment_Config__mdt amac = acctMgrAssignmentConfig_map.get(accountMgrTypeValue);
        
        //If we have values for this label then lets set those values after we check and split the string up.
        //Otherwise set some default values.
        if(amac != null){
            List<String> caseTypeArray = new List<String>();
            //Make sure the string is not blank before we try to split based off the key passed in.
            //If it is blank then set some default values.
            if(String.isNotBlank(amac.Value__c)){
                caseTypeArray = amac.Value__c.split(',');
                
                for(String cta : caseTypeArray){
                    caseRecordTypeIds.add(caseTypes.get(cta.trim()));
                }
            } else {
                if(acctMgrType.equals('TAM')){
                    caseRecordTypeIds.add(caseTypes.get('Support_Cases'));
                } 
                if(acctMgrType.equals('SAM')){
                    caseRecordTypeIds.add(caseTypes.get('Success_Team_Cases'));           
                }
            }
        } else {
            //Set Defaults if non are set prior
            if(acctMgrType.equals('TAM')){
                caseRecordTypeIds.add(caseTypes.get('Support_Cases'));
            } 
            if(acctMgrType.equals('SAM')){
                caseRecordTypeIds.add(caseTypes.get('Success_Team_Cases'));           
            }
        }
        
        return caseRecordTypeIds;
    }
When I call this method with "SAM", I should get back a list of two case record type id's, but I am not. I am only getting what should be the first record id in the list.

If I uncomment the System.Debug statement right after the List<Id> initialization, I get both record type id's like I should. This manifests itself in two different ways in two different environments. In one environment, a test method assertion fails, but it works fine when I am using the functionality as the user would in Salesforce, while in another environment it doesn't work for the user (I haven't tried the test method yet). 

Mainly, what I am looking for is any possible explanation as to why putting the System.Debug statement would cause the List to eventually be built correctly (with the two expected case record ids) and when removing or commenting out the System.Debug the List appears to have only one value in the List. It literally comes down to me "fixing" the issue by just adding a System.Debug statement to view the initialized empty list. Does anyone know anything about what could be going on behind the scenes when Salesforce is executing this code? 

Thanks for any insight. Just to be clear, I am not looking for anyone to solve this issue, I am looking for possible explanations as to why I am seeing this strange behavior when adding the System.Debug or any ideas on what else I could try to look at.
Best Answer chosen by Ken Fitzpatrick 10
Ken Fitzpatrick 10Ken Fitzpatrick 10
So, I wasn't clear in my last post where I showed the results of my debug statements. The function I posted in my original post is used to build a list of case record type ids. The code that calls this method then uses the List.Contains() method to see if there is a certain value in the List. That is actually what is causing my code not to work. It looks like there is a known bug with the List.Contains() method that manifests under certain conditions (like changing some state/context of that List when I add the debug line). (See https://salesforce.stackexchange.com/questions/224490/bug-in-list-contains-for-id-data-type).

As a solution to my issue, instead of using a List<Id> to store my record id list and return from the function, I changed it to a Set<Id>, which is a way better fit for this scenario anyway. The Contains method for Set doesn't have the same issues as the List and works as expected. I did try using the List.IndexOf() method instead of List.Contains() at one point, but it suffers from the same or similar bug as List.Contains(). As a side note, it would be great if Salesforce gave us the ability to extend and override some of the classes like System.List. If we could, you could create a List2 that extends List and override the Contains or IndexOf method to actually work. 

All Answers

Ken Fitzpatrick 10Ken Fitzpatrick 10
So, as an update, the metadata value that is used to build the List<Id> that the method returns is "Success_Team_Cases, Support_Cases". If I switch it to "Support_Cases, Success_Team_Cases" (without the debug line), it works. Another alternative that works is changing the method to return a string and build the list of case record type ids in a comma-delimited string instead of a List<Id>. So, I am still baffled how all these hacks work, but the original code does not.
SUCHARITA MONDALSUCHARITA MONDAL
Hi Ken,

The debug on Line 03--> shouldn't return anything as caseRecordTypeIds is blank/as just initialized. You should put you debug statement before return statement ( before Line 39.) because by then caseRecordTypeIds  list will have some values.

PS. You can always check size of list as System.debug('--size--'+caseRecordTypeIds .size());

Share your thoughts!

Thanks,
Sucharita
Ken Fitzpatrick 10Ken Fitzpatrick 10
Thanks for the response, but that wasn't what I was asking. Without the debug statement, my function (getCaseRecordTypes) is returning one value in the list. With the debug statement, my function is returning two values in the list. In this case, my function (getCaseRecordTypes) should return two values (a record id for "Success_Team_Cases" and a record id for "Support_Cases"), so just by adding that debug statement, causes my code to run correctly. Without the debug statement, my code does not run correctly. I am asking for any explanation as to why adding a debug statement where I did causes my code to run correctly.

 
Ken Fitzpatrick 10Ken Fitzpatrick 10
Ok, I narrowed it down to this; without the debug statement referencing the List, the List.contains() method cannot find the last element in the List. In this case, the last element is the record id for "Support_Cases". If I switch the metadata values around, the record id for "Support_Cases" is first in the list and it can find it. That's why it worked when I switched the metadata types around. Here are the debug lines that show this behavior (note: samCaseRecordTypes is the List<Id> variable):

[No Debug Line - Contains cannot find the last element]
14:06:09.125 (25806418068)|USER_DEBUG|[36]|ERROR|*** Kentest (samCaseRecordTypes.size()) 2
14:06:09.125 (25806454824)|USER_DEBUG|[38]|ERROR|*** Kentest (samCaseRecordTypes.get(0)) 012400000005gHLAAY
14:06:09.125 (25806480505)|USER_DEBUG|[39]|ERROR|*** Kentest (samCaseRecordTypes.contains(samCaseRecordTypes.get(0))) true
14:06:09.125 (25806508653)|USER_DEBUG|[42]|ERROR|*** Kentest (samCaseRecordTypes.get(1)) 012400000005gHBAAY
14:06:09.125 (25806560470)|USER_DEBUG|[43]|ERROR|*** Kentest (samCaseRecordTypes.contains(samCaseRecordTypes.get(1))) false
14:06:09.125 (25806590657)|USER_DEBUG|[45]|ERROR|*** Kentest (c.RecordTypeId) 012400000005gHBAAY
14:06:09.125 (25806924107)|USER_DEBUG|[47]|ERROR|*** Kentest (samCaseRecordTypes.contains(c.RecordTypeId)) false

[With Debug Line - Contains can find the last element]
14:10:00.181 (24869667536)|USER_DEBUG|[36]|ERROR|*** Kentest (samCaseRecordTypes.size()) 2
14:10:00.181 (24869708088)|USER_DEBUG|[38]|ERROR|*** Kentest (samCaseRecordTypes.get(0)) 012400000005gHLAAY
14:10:00.181 (24869730391)|USER_DEBUG|[39]|ERROR|*** Kentest (samCaseRecordTypes.contains(samCaseRecordTypes.get(0))) true
14:10:00.181 (24869750329)|USER_DEBUG|[42]|ERROR|*** Kentest (samCaseRecordTypes.get(1)) 012400000005gHBAAY
14:10:00.181 (24869767313)|USER_DEBUG|[43]|ERROR|*** Kentest (samCaseRecordTypes.contains(samCaseRecordTypes.get(1))) true
14:10:00.181 (24869782580)|USER_DEBUG|[45]|ERROR|*** Kentest (c.RecordTypeId) 012400000005gHBAAY
14:10:00.181 (24870067743)|USER_DEBUG|[48]|ERROR|*** Kentest (samCaseRecordTypes.contains(c.RecordTypeId)) true
14:10:00.181 (24870081570)|USER_DEBUG|[50]|ERROR|*** Kentest Found a record type

[No Debug Line, values swapped - Contains finds the right element because it is now first. Second element still not found]
14:02:29.119 (28897808586)|USER_DEBUG|[27]|ERROR| ***** Kentest (caseRecordTypeIds.size()) --> 2
14:02:29.119 (28898094870)|USER_DEBUG|[36]|ERROR|*** Kentest (samCaseRecordTypes.size()) 2
14:02:29.119 (28898136484)|USER_DEBUG|[38]|ERROR|*** Kentest (samCaseRecordTypes.get(0)) 012400000005gHBAAY
14:02:29.119 (28898167694)|USER_DEBUG|[39]|ERROR|*** Kentest (samCaseRecordTypes.contains(samCaseRecordTypes.get(0))) true
14:02:29.119 (28898199295)|USER_DEBUG|[42]|ERROR|*** Kentest (samCaseRecordTypes.get(1)) 012400000005gHLAAY
14:02:29.119 (28898244306)|USER_DEBUG|[43]|ERROR|*** Kentest (samCaseRecordTypes.contains(samCaseRecordTypes.get(1))) false
14:02:29.119 (28898276316)|USER_DEBUG|[45]|ERROR|*** Kentest (c.RecordTypeId) 012400000005gHBAAY
14:02:29.119 (28898664715)|USER_DEBUG|[48]|ERROR|*** Kentest (samCaseRecordTypes.contains(c.RecordTypeId)) true
14:02:29.119 (28898707538)|USER_DEBUG|[50]|ERROR|*** Kentest Found a record type

So, there is apparently some weird-ass bug with the List/contains method. I did try to reproduce from the Execute Anonymous Window and I could not reproduce, so it has something to do with the execution context it runs in. 

Has anyone else seen this issue before or know of some environment setting to fix it?
Ken Fitzpatrick 10Ken Fitzpatrick 10
So, I wasn't clear in my last post where I showed the results of my debug statements. The function I posted in my original post is used to build a list of case record type ids. The code that calls this method then uses the List.Contains() method to see if there is a certain value in the List. That is actually what is causing my code not to work. It looks like there is a known bug with the List.Contains() method that manifests under certain conditions (like changing some state/context of that List when I add the debug line). (See https://salesforce.stackexchange.com/questions/224490/bug-in-list-contains-for-id-data-type).

As a solution to my issue, instead of using a List<Id> to store my record id list and return from the function, I changed it to a Set<Id>, which is a way better fit for this scenario anyway. The Contains method for Set doesn't have the same issues as the List and works as expected. I did try using the List.IndexOf() method instead of List.Contains() at one point, but it suffers from the same or similar bug as List.Contains(). As a side note, it would be great if Salesforce gave us the ability to extend and override some of the classes like System.List. If we could, you could create a List2 that extends List and override the Contains or IndexOf method to actually work. 
This was selected as the best answer