[SalesForce] Getting System.FinalException: Record is read-only when PB calls an apex class

I am getting this error whenever my Process builder calls an Apex Class. I'm not sure if this is allowed so I'd like to ask for your input.

So basically, my Process Builder is in the Case object and it is triggered when User sends an email to a Queue.

When this happens, the Process Builder then calls an Apex class with an invocable method below:

    @InvocableMethod
    public static void methodA(List<Case> caseList) {

    //do some SOQL code here to determine xxxxxxxx

    for(Case c : caseList) {
        c.contactId = 'xxxxxxxx';
    }        
    update caseList;        
    }

Basically, the method just changes the contact Id of the case to something else and then updates the Case.

However, I instead get this error every time I send an email to the Queue.

An Apex error occurred: System.FinalException: Record is read-only

It would seem that I am not allowed to update the contactId of the Case. Is this correct?
If so, then how can I update the contactId of the Case by the Apex Class?

Thanks.

Best Answer

let me guess, that records, that are sent to Apex are sent from Process as "Select the Case record that started your process". According to the Order of Execution process is launched after after triggers. And if you are sending context records, looks like they all have "isReadOnly" flag on the sObject records. This flag is responsible for causing the FinalException. This is similar to situation, when you are trying to change trigger context records in after trigger event. In order to update records from current transaction, create new Case record with predefined Id.

@InvocableMethod
public static void methodA(List<Case> caseList) {
    List<Case> toUpdate = new List<Case>();
    for(Case c : caseList) {
        toUpdate.add(new Case(
            Id = c.Id,
            ContactId = 'xxxxxxxx';
        ));
    }
    update toUpdate;
}