+ Start a Discussion

Exeception on After Insert, Record is read only

I'm writing a trigger for new opportunity products to populate a field Product_Category__c (on opportunity lineitem) getting the value from Product_Category_new__c (on Product).

This is my trigger:

trigger SetProductCategory on OpportunityLineItem (after insert) {

            for (OpportunityLineItem opplineitem: Trigger.new){

                         opplineitem.Product_Category__c= opplineitem.PricebookEntry.Product2.Product_Category_new__c;


I get this error message:

execution of AfterInsert caused by: System.FinalException: Record is read-only

I have tried with before insert;in this case there aren't errors but the value Product category it's not saved on Opportunity Line item.


I have found that:

In a after insert trigger is not allowed change field using trigger.new


Please can you suggest a solution for this? i would like to copy the value Product category (Product) on Product Category (Opportunity Product) after the insert of the new opportunity products.

Thanks in advantage for any advice.




trigger SetProductCategory on OpportunityLineItem (after insert) {

    List<OpportunityLineItem> olis = [SELECT Id, PricebookEntry.Product2.Product_Category_new__c FROM OpportunityLineItem WHERE Id IN: Trigger.newMap.keySet()];

    for (OpportunityLineItem o :olis){
        o.Product_Category__c= o.PricebookEntry.Product2.Product_Category_new__c;

    update olis;



Well excellent!
I was wondering, and seems like this can be achieved by workflows.
Please not that "You can use an object to change its own field values using trigger.new, but only in before triggers. In all after triggers, trigger.new is not saved, so a runtime exception is thrown."

Refrence : https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_triggers_context_variables_considerations.htm
Bhanu joshi 10Bhanu joshi 10

You can Change after insert to before insert.
The error is comming because  in after insert/update trigger and the records are in read only mode as they are not committed in the database.

Eric PepinEric Pepin
trigger SetProductCategory on OpportunityLineItem(before insert) {
    for (OpportunityLineItem o : Trigger.New) {
        o.Product_Category__c = o.PricebookEntry.Product2.Product_Category_new__c;
No SOQL or UPDATE statement needed in Before trigger context.
Glyn Anderson 3Glyn Anderson 3
Eric Pepin has the right idea setting the field in the before trigger; but you won't get the Product_Category_new__c field unless you query it.  Records in a trigger only have their own fields - not any fields across a relationship.  So all your Product_Category__c fields will be null,  Gdev20000 did the necessary query, but tries to update a record that is already in the trigger.  This won't work because you can't do DML on a record that's already in the trigger - it hasn't been committed to the database yet.  I suggest something like this - a hybrid of the two solutions:

trigger SetProductCategory on OpportunityLineItem( before insert )
    for ( OpportunityLineItem queriedOLI :
    [   SELECT  Id, PricebookEntry.Product2.Product_Category_new__c
        FROM    OpportunityLineItem 
        WHERE   Id IN :Trigger.new
        Trigger.newMap.get( queriedOLI.Id ).Product_Category__c = queriedOLI.PricebookEntry.Product2.Product_Category_new__c;
Glyn Anderson 3Glyn Anderson 3
Gdev20000,  Did any of these answers solve your problem?  If so, please mark the question as "Solved".  If not, let us know.  If you solved it yourself another way, please post your solution.  Thanks!