Invocable method gets readonly accounts from PB, which need to be re-instantiated before updating, here's a solution I tried and it works:

        public static void run(List<Account> myAccounts) {
            List<Account> accsToUpdate = new List<Account>();
            for(Account acc : myAccounts){
                 //-- omitted if statement
                accsToUpdate.add( new Account(
                    Id = acc.Id,
                    Last_stage_change_date__c = Date.today(),
                    Score__c = someVar
        update accsToUpdate;

is this a safe and equivalent alternative to updating records by first retrieving them by SOQL (using Account Ids received from PBuilder)?

I guess same goes for any Apex context: do I need to SOQL if i know the record ID and just need to update it? thanks


If the records involved have already been locked by the database, this is a guaranteed safe operation. For example, handling the ID values from a Process Builder that passes in the ID values from the records currently being operated on is perfectly safe, as those records are already locked. However, if the records have not yet been locked, a DML operation could fail if another process locks those records in the interim.

So, this requires some analysis. For an ISV, it's probably a bad idea to write this type of logic unless you can guarantee the records are already locked (e.g. the action only works on the currently processing records somehow), but if you are in control of your environment, then this analysis should be easy to understand.

If you're not sure, it's better to burn a query and make sure you have locked the records. Remember to use the FOR UPDATE keyword to lock the records before attempting to perform a DML operation.

  • If you are sure that you don't need to lock, why create the accsToUpdate list? Wouldn't you use ...acc.Last_stage_change_date__c = Date.today(), acc.Score__c = someVar)); } update myAccounts; ?
    – MikeA
    Jan 5 at 22:40
  • 1
    @MikeA I didn't address that, but yes, you could directly use the values passed in from the flow/process instead of creating a copy.
    – sfdcfox
    Jan 6 at 0:11
  • 1
    @MikeA If I try to do that, I get this in UI : An Apex error occurred: System.FinalException: Record is read-only Hence my solution (create copy list) follows advice shown in this answer: salesforce.stackexchange.com/a/233861/49190 Jan 6 at 16:45
  • @Dextersecret Oh, that makes sense, actually. Good reminder to test things out. I'll have to remember that for later.
    – sfdcfox
    Jan 6 at 17:18
  • Good to point that out @Dextersecret, very useful.
    – MikeA
    Jan 6 at 17:25

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.