0

I am getting an error while application of trigger ,the error is "Apex trigger SubStatus_update caused an unexpected exception, contact your administrator: SubStatus_update: execution of AfterUpdate caused by:

System.FinalException: Record is read-only: Trigger.SubStatus_update: line 4, column 1"

and my code is

trigger SubStatus_update on Project__c (after insert, after update) {
 for(Project__c p : trigger.new){
         if(p.Status__c == 'Pending'){
               p.Sub_Status__c='Project Pending';
             }
     }   
}  
1
  • 2
    Honestly, you could just use a workflow/Process Builder to do this. You should resort to code only when configuration isn't sufficient for your purposes.
    – sfdcfox
    Oct 10 '16 at 21:36
2

Ambika,

==UPDATE==

As you can see in the comments below, my code is very pretty but would take you in an infinite loop unless you build some safeguards. I updated my code to show you one possible pattern.

Recommendation is to move your original post to a BEFORE trigger.

==ORIGINAL POST== (fixed for Infinite Loop)

Objects are read only in "After" triggers. In them, you have to re-query and update.

For example, your code could look like this:

trigger SubStatus_update on Project__c (after insert, after update) {

  ProjectTriggerMethods.updateSubStatus();

}



public with sharing class ProjectTriggerMethods () {
     public static boolean hasRun = false;

     public static void updateSubStatus() {
       if (hasRun) {
         return;
      }

      hasRun = true;

      Set<Id> projectIDs = new Set<Id>();

      for(Project__c p : trigger.new){
         if(p.Status__c == 'Pending'){
            projectIDs.add(p.id);    
          }
      }   

       List<Project__c> projects = [select Status__c from Project__c where Id in :projectIDs];
       for(Project__c p : projects){    
              p.Sub_Status__c='Project Pending';
       }

      update projects;
     }
   }

Alternatively, you can move your code to "before" triggers. This code will work just fine there.

4
  • I think a before trigger is more appropriate here, as OP's code doesn't rely on having the Id available, and is working on the same sObject that the trigger is defined on.
    – Derek F
    Oct 10 '16 at 21:32
  • We can't know if there is logic in the "Before" trigger that would conflict with this behavior. Hence I suggested the code change and added my note at the end. Oct 10 '16 at 21:34
  • 1
    This answer would result in an infinite loop once the status hits pending. Before insert is the correct way to go about it. And, there's no need to query the records back when you already have the Id values for the records.
    – sfdcfox
    Oct 10 '16 at 21:34
  • Good catch on the infinite loop, @sfdcfox. I somehow didn't realize that it was 2 different fields. Oct 10 '16 at 21:38

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.