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
k2018123k2018123 

trigger read only errors

HI,
I have. a trigger which is working fine. But i want to update the record value of the object but getting "execution of AfterInsert caused by: System.FinalException: Record is read-only" error. After processing all the records i want to again update the same object record value. Can somebody help. Below is my code snippet. I have commented the code which is not working fine:
public class JobTriggerHandler
{
    public void onAfterInsert(List<Job_Control__c> lstNewObjA)
    {
        Set<String> setUniqueId = new Set<String>();
        Set<String> objAStatus = new Set<String>();
        for(Job_Control__c objA : lstNewObjA)
        {
            if(String.isNotBlank(objA.Unique_Id__c ) && objA.Status__c == 'Under Processing')
            {
                setUniqueId.add(objA.Unique_Id__c );
                // objA.Status__c = 'With CRM';
                
            }
        }
        // if(lstNewObjA.size() > 0){
        //    update lstNewObjA;
        //}
        if(!setUniqueId.isEmpty())
        {
            List<Staging_Course__c> lststag = new List<Staging_Course__c>();
            List<Course__c> lstObjC = new List<Course__c >();
            for(Staging_Course__c  objB: [SELECT test_Field__c , test_field_1__c,name  FROM Staging_Course__c WHERE Unique_Id__c  IN: setUniqueId])
            {
                
                lstObjC.add(new Course__c( test_Field__c  = objB.test_Field__c, test_field_1__c  = objB.test_field_1__c , name = objB.name ));
                objB.Status__c = 'Completed'; 
                lststag.add(objB);
                
            }
            if(!lststag.isEmpty())
                update lststag;
            
            if(!lstObjC.isEmpty())
                insert lstObjC;
            /* for(Job_Control__c objAUpdated : lstNewObjA)
{

objAUpdated.Status__c = 'Completed';

}

if(lstNewObjA.size() > 0){
update lstNewObjA;
}*/ 
            
        }
        
    } 
    
}

 
Best Answer chosen by k2018123
Maharajan CMaharajan C
Hi,

In the After dml you can't Edit the Trigger.New() Lists because the Trigger.New() list become readonly so that you recieved this Error.

To avoid this you to follow the below Options:

1, Change the DML to Before Events bacause only in the Before DML Events the Trigger.New() is Editable.
2. Use the SOQL to query the Triiger.New() records as like RAJ V suggestion.
3. And one more suggestion create the new List and initiate the Record against Trigger.New() below it will avoid extra SOQL.


public class JobTriggerHandler
{
    public void onAfterInsert(List<Job_Control__c> lstNewObjA)
    {
        Set<String> setUniqueId = new Set<String>();
        Set<String> objAStatus = new Set<String>();
        List<Job_Control__c> LstJobtoUpdate = new List<Job_Control__c>();
        for(Job_Control__c objA : lstNewObjA)
        {
            if(String.isNotBlank(objA.Unique_Id__c ) && objA.Status__c == 'Under Processing')
            {
                setUniqueId.add(objA.Unique_Id__c );
                // objA.Status__c = 'With CRM';
                
            }
        }
        // if(lstNewObjA.size() > 0){
        //    update lstNewObjA;
        //}
        if(!setUniqueId.isEmpty())
        {
            List<Staging_Course__c> lststag = new List<Staging_Course__c>();
            List<Course__c> lstObjC = new List<Course__c >();
            for(Staging_Course__c  objB: [SELECT test_Field__c , test_field_1__c,name  FROM Staging_Course__c WHERE Unique_Id__c  IN: setUniqueId])
            {
                
                lstObjC.add(new Course__c( test_Field__c  = objB.test_Field__c, test_field_1__c  = objB.test_field_1__c , name = objB.name ));
                objB.Status__c = 'Completed'; 
                lststag.add(objB);
                
            }
            if(!lststag.isEmpty())
                update lststag;
            
            if(!lstObjC.isEmpty())
                insert lstObjC;
            for(Job_Control__c objAUpdated : lstNewObjA)
            {
            Job_Control__c j = new Job_Control__c(id = objAUpdated.Id);
            j.Status__c = 'Completed';
            LstJobtoUpdate.add(j)
;
            }

            if(LstJobtoUpdate.size() > 0){
            update LstJobtoUpdate;

            }
            
        }
        
    } 
    
}

Can you please Let me know if it helps or not!!!

If it helps don't forget to mark this as a best answer!!!


Thanks,
Raj

All Answers

Raj VakatiRaj Vakati
You need to Query the same record and  then update it 
Raj VakatiRaj Vakati
Bulkify this code 
 
public class JobTriggerHandler
{
    public void onAfterInsert(List<Job_Control__c> lstNewObjA)
    {
        Set<String> setUniqueId = new Set<String>();
        Set<String> objAStatus = new Set<String>();
        for(Job_Control__c objA : lstNewObjA)
        {
            if(String.isNotBlank(objA.Unique_Id__c ) && objA.Status__c == 'Under Processing')
            {
                setUniqueId.add(objA.Unique_Id__c );
                // objA.Status__c = 'With CRM';
                
            }
        }
        // if(lstNewObjA.size() > 0){
        //    update lstNewObjA;
        //}
        if(!setUniqueId.isEmpty())
        {
            List<Staging_Course__c> lststag = new List<Staging_Course__c>();
            List<Course__c> lstObjC = new List<Course__c >();
            for(Staging_Course__c  objB: [SELECT test_Field__c , test_field_1__c,name  FROM Staging_Course__c WHERE Unique_Id__c  IN: setUniqueId])
            {
                
                lstObjC.add(new Course__c( test_Field__c  = objB.test_Field__c, test_field_1__c  = objB.test_field_1__c , name = objB.name ));
                objB.Status__c = 'Completed'; 
                lststag.add(objB);
                
            }
            if(!lststag.isEmpty())
                update lststag;
            
            if(!lstObjC.isEmpty())
                insert lstObjC;
			
			Set<id> ids = new Set<Id>();
            for(Job_Control__c objAUpdated : lstNewObjA)
{
ids.add(objAUpdated.Id) ; 
//objAUpdated.Status__c = 'Completed';

}

for(Job_Control__c  obj : [Select Id,Status__c from Job_Control__c where id in :ids]){
	obj.Status__c = 'Completed'; 
	update obj ; 
	
}

            
        }
        
    } 
    
}

 
Maharajan CMaharajan C
Hi,

In the After dml you can't Edit the Trigger.New() Lists because the Trigger.New() list become readonly so that you recieved this Error.

To avoid this you to follow the below Options:

1, Change the DML to Before Events bacause only in the Before DML Events the Trigger.New() is Editable.
2. Use the SOQL to query the Triiger.New() records as like RAJ V suggestion.
3. And one more suggestion create the new List and initiate the Record against Trigger.New() below it will avoid extra SOQL.


public class JobTriggerHandler
{
    public void onAfterInsert(List<Job_Control__c> lstNewObjA)
    {
        Set<String> setUniqueId = new Set<String>();
        Set<String> objAStatus = new Set<String>();
        List<Job_Control__c> LstJobtoUpdate = new List<Job_Control__c>();
        for(Job_Control__c objA : lstNewObjA)
        {
            if(String.isNotBlank(objA.Unique_Id__c ) && objA.Status__c == 'Under Processing')
            {
                setUniqueId.add(objA.Unique_Id__c );
                // objA.Status__c = 'With CRM';
                
            }
        }
        // if(lstNewObjA.size() > 0){
        //    update lstNewObjA;
        //}
        if(!setUniqueId.isEmpty())
        {
            List<Staging_Course__c> lststag = new List<Staging_Course__c>();
            List<Course__c> lstObjC = new List<Course__c >();
            for(Staging_Course__c  objB: [SELECT test_Field__c , test_field_1__c,name  FROM Staging_Course__c WHERE Unique_Id__c  IN: setUniqueId])
            {
                
                lstObjC.add(new Course__c( test_Field__c  = objB.test_Field__c, test_field_1__c  = objB.test_field_1__c , name = objB.name ));
                objB.Status__c = 'Completed'; 
                lststag.add(objB);
                
            }
            if(!lststag.isEmpty())
                update lststag;
            
            if(!lstObjC.isEmpty())
                insert lstObjC;
            for(Job_Control__c objAUpdated : lstNewObjA)
            {
            Job_Control__c j = new Job_Control__c(id = objAUpdated.Id);
            j.Status__c = 'Completed';
            LstJobtoUpdate.add(j)
;
            }

            if(LstJobtoUpdate.size() > 0){
            update LstJobtoUpdate;

            }
            
        }
        
    } 
    
}

Can you please Let me know if it helps or not!!!

If it helps don't forget to mark this as a best answer!!!


Thanks,
Raj
This was selected as the best answer
k2018123k2018123
Hi,

Yes, working fine now. Thanks Maharajan and Raj. Both the approach works fine.