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
Mamadou Diallo 14Mamadou Diallo 14 

Error: System.ListException: Duplicate id in list

Hello,

I have trigger that will update a custom field Segment__c on the account based on the owner Role Description. I'm getting this error when I change the owner of the account to someone in the Operations department:
Error: Apex trigger SegmentRulesTrigger caused an unexpected exception, contact your administrator: SegmentRulesTrigger: execution of AfterUpdate

caused by: System.ListException: Duplicate id in list:

Here is the part of the trigger that is not working:
trigger SegmentRulesTrigger on Account (after insert, after update) {
    
    //Create a list of accounts to update 
    List<Account> acctsListToUpdate = new List<Account>(); 
   
   
	//check if trigger is running again
    if(RecursiveTriggerHandler.runOnce()){
    
        for (Account a : Trigger.new) {
         //Query the owner role description
			for(User u : [SELECT id, Role_Description__c FROM User WHERE id = :a.OwnerId]){
				// Check if the account ID is not null 
				// to avoid "referencing null object" error       
				if(a != NULL  && a.ID !=NULL){
				// create a placeholder account a1    
				Account a1  = new Account(Id = a.Id, Name = a.Name, OwnerId = a.OwnerId);
				
					//Map Account ID
					Account oldAcct = Trigger.oldMap.get(a1.Id);
									//Check if Account Owner or Name has changed
								   if (oldAcct.OwnerId != a1.OwnerId || oldAcct.Name != a1.Name){
									//  User u1 = new User(Id= u.Id, Role_Description__c = u.Role_Description__c);
										//Check if Owner role description is Operations
									   if( u.Role_Description__c == 'Operations' )
											 {
											  a1.Segment__c = 'Other';
											  acctsListToUpdate.add(a1); 
										}
											 a1.Segment__c = u.Role_Description__c;
											 acctsListToUpdate.add(a1); 
									 } 
								
				} 
                //Bulkify the update    
                if(acctsListToUpdate.size()>0){
                    update acctsListToUpdate;            
                } 
			}				
		}	
	}
}

Thank you for your help.​
Best Answer chosen by Mamadou Diallo 14
Deepak Maheshwari 7Deepak Maheshwari 7

Hi,

 

Please try below compact and refined code:

 

trigger SegmentRulesTrigger on Account (before insert, before update) {
    
  
   Set<Id> ownerIds = new Set<Id>();
    
   if(RecursiveTriggerHandler.runOnce()){
    
        for (Account a : Trigger.new) {
        ownerIds.add(a.ownerId);
        
        }
    
Map<Id,User> userMap = new Map<Id,User>([Select Id,Role_Description__c From User where Id IN :ownerIds]);
        for(Account acc : Trigger.New)
        {
            if(userMap.containskey(acc.OwnerId))
            {
                if(userMap.get(acc.OwnerId).Role_Description__c=='Operations')
                {
                    acc.Segment__c='Other';
                }
                else
                {
                    acc.Segment__c=userMap.get(acc.OwnerId).Role_Description__c;
                }
            }
        }
     }
  }

All Answers

Mamadou Diallo 14Mamadou Diallo 14
Hello Deepak,

Thank you for taking the time to work on my issue. I don't see difference between your code and mine. Can you point me to the changes you made to my code?

Thanks again.
Manohar kumarManohar kumar

hi,

pls try like this..

before updating put it in a set and then again in a list,and then update.

if(
    acctsListToUpdate.size()>0){ 

Set<Account> myset = new Set<Account>();
List<Account> result = new List<Account>(); 
myset.addAll(acctsListToUpdate);
 result.addAll(myset);

        update result; }
 

pls try like this. Let me know if this does not work.

Thanks,

Manohar

 

Deepak Maheshwari 7Deepak Maheshwari 7
Can you please confirm the code is working or not?
kavya rao neelagirikavya rao neelagiri
Hi,

You are getting this error because you are inserting account 2 times into a list in a single loop. So, when you update the list having duplicate ID will cause an issue.
You should add else to avoid this in your code
if (oldAcct.OwnerId != a1.OwnerId || oldAcct.Name != a1.Name){
                                 //  User u1 = new User(Id= u.Id, Role_Description__c = u.Role_Description__c);
                                       //Check if Owner role description is Operations
                                       if( u.Role_Description__c == 'Operations' )
                                             {
                                              a1.Segment__c = 'Other';
                                              acctsListToUpdate.add(a1);
                                             }
                                        else{
                                             a1.Segment__c = u.Role_Description__c;
                                             acctsListToUpdate.add(a1);
                                              }
                                     }
                                 
                }
Mamadou Diallo 14Mamadou Diallo 14
Thank you Deepak but I used Manohar code and ir worked. Now the issue I'm facing is when the user creates a new account, I got the error:
Attempt to de-reference a null object: ()

 
Manohar kumarManohar kumar

Hi Mamadou,

in which line you are getting null pointer, can you pls post your code..

Thanks,

Manohar

Deepak Maheshwari 7Deepak Maheshwari 7

Hi,

 

Please try below compact and refined code:

 

trigger SegmentRulesTrigger on Account (before insert, before update) {
    
  
   Set<Id> ownerIds = new Set<Id>();
    
   if(RecursiveTriggerHandler.runOnce()){
    
        for (Account a : Trigger.new) {
        ownerIds.add(a.ownerId);
        
        }
    
Map<Id,User> userMap = new Map<Id,User>([Select Id,Role_Description__c From User where Id IN :ownerIds]);
        for(Account acc : Trigger.New)
        {
            if(userMap.containskey(acc.OwnerId))
            {
                if(userMap.get(acc.OwnerId).Role_Description__c=='Operations')
                {
                    acc.Segment__c='Other';
                }
                else
                {
                    acc.Segment__c=userMap.get(acc.OwnerId).Role_Description__c;
                }
            }
        }
     }
  }
This was selected as the best answer
Mamadou Diallo 14Mamadou Diallo 14
Here is the code I'm using:
 
trigger SegmentRulesTrigger on Account (after insert, after update) {
    
    //Create a list of accounts to update 
    List<Account> acctsListToUpdate = new List<Account>(); 
   
   
	//check if trigger is running again
    if(RecursiveTriggerHandler.runOnce()){
    
        for (Account a : Trigger.new) {
         //Query the owner role description
			for(User u : [SELECT id, Role_Description__c FROM User WHERE id = :a.OwnerId]){
				// Check if the account ID is not null 
				// to avoid "referencing null object" error       
				if(a != NULL  && a.ID !=NULL){
				// create a placeholder account a1    
				Account a1  = new Account(Id = a.Id, Name = a.Name, OwnerId = a.OwnerId);
				
					//Map Account ID
					Account oldAcct = Trigger.oldMap.get(a1.Id);
									//Check if Account Owner or Name has changed
								   if (oldAcct.OwnerId != a1.OwnerId || oldAcct.Name != a1.Name){
									//  User u1 = new User(Id= u.Id, Role_Description__c = u.Role_Description__c);
										//Check if Owner role description is Operations
									   if( u.Role_Description__c == 'Operations' )
											 {
											  a1.Segment__c = 'Other';
											   
										}
										else{
										a1.Segment__c = u.Role_Description__c;
										}
											 
											 acctsListToUpdate.add(a1); 
									 } 
								
				} 
                          
                } 
			}
			//Bulkify the update    
                if(
					acctsListToUpdate.size()>0){ 

					Set<Account> myset = new Set<Account>();
					List<Account> result = new List<Account>(); 
					myset.addAll(acctsListToUpdate);
					result.addAll(myset);

					update result; 
					}
	}
}

When I edit a single record, I don't have errror.

When I create a new account, I have this error 
Attempt to de-reference a null object: ()
I used Data Loader to bulk reassign accounts (batch 200), I got this error
SegmentRulesTrigger: System.LimitException: Apex CPU time limit exceeded

Deepark, I'm trying your code. I will keep you updated.
 
Deepak Maheshwari 7Deepak Maheshwari 7

Hi,

 

Yes please try my code and keep me posted if any issue arises

Mamadou Diallo 14Mamadou Diallo 14
Thank you Deepak for your help. Your code worked.

Thank you Manohar for your help.

 
Mamadou Diallo 14Mamadou Diallo 14
Now I'm facing CPU Limit Exceded on a different code when I bulk upload accounts:
trigger SyncAccountAndContactOwner on Account (after update) {
  
      Set<Id> accountIds = new Set<Id>(); 
      Map<Id, String> oldOwnerIds = new Map<Id, String>();
      Map<Id, String> newOwnerIds = new Map<Id, String>();
      List<Contact> ListContactsToUpdate = new List<Contact>(); 
     
      for (Account a : Trigger.new) 
      { 
         if (a.OwnerId != Trigger.oldMap.get(a.Id).OwnerId) 
         {
            oldOwnerIds.put(a.Id, Trigger.oldMap.get(a.Id).OwnerId); 
            newOwnerIds.put(a.Id, a.OwnerId); 
            accountIds.add(a.Id); 
         }
      }
        if (!accountIds.isEmpty()) { 
         for (Account act : [SELECT Id, (SELECT Id, OwnerId FROM Contacts) FROM Account WHERE Id in :accountIds])
            {
            String newOwnerId = newOwnerIds.get(act.Id); 
            String oldOwnerId = oldOwnerIds.get(act.Id); 
            for (Contact c : act.Contacts) 
            { 
               if (c.OwnerId == oldOwnerId)
               {
               Contact updatedContact = new Contact(Id = c.Id, OwnerId = newOwnerId);
               ListContactsToUpdate.add(updatedContact);
               }
            }
            
            }
       }
            update ListContactsToUpdate;
}

 
Deepak Maheshwari 7Deepak Maheshwari 7

Hi,

 

Can you please let me know how many triggers are there on account?

Mamadou Diallo 14Mamadou Diallo 14
There's one and I'm adding 2 ( SyncAccountAndContactOwner and SegmentRulesTrigger). We have other trigger installed from Managed Packages.
Deepak Maheshwari 7Deepak Maheshwari 7

Ideally there should be only 1 trigger on 1 object.

 

You need to merge all the triggers in 1 and put all three triggers logic in 1 handler class.

CPU time limit error generally comes when nested for loops are there. Please avoid them and use Map in place of them.

Deepak Maheshwari 7Deepak Maheshwari 7

You can share all three triggers on below email address:


dpkm20@gmail.com