+ Start a Discussion
SimrinSimrin 

recordTypeid is read only error

trigger UsableUpdateTrigger on EFX_WorkItem__c (after insert, after update, after delete) {
for (EFX_WorkItem__c w: trigger.new) {
if(Trigger.isUpdate){
    EFX_WorkItem__c recordIdOfParent = [SELECT recordTypeid FROM EFX_WorkItem__c WHERE Parent_Item__c =:w.Parent_Item__c limit 1];
    RecordType idLevel0 = [Select Id From RecordType Where Name ='Level 0 Task' limit 1];
    RecordType idLevel1 = [Select Id From RecordType Where Name ='Level 1 Task' limit 1];
    RecordType idLevel2 = [Select Id From RecordType Where Name ='Level 2 Task' limit 1];
    RecordType idLevel3 = [Select Id From RecordType Where Name ='Level 3 Task' limit 1];
    if(recordIdOfParent!=null){
        if(recordIdOfParent.recordTypeid == idLevel3.Id){
        }else if(recordIdOfParent.recordTypeid  == idLevel2.Id){
            w.recordTypeid = idLevel3.Id;  //record is read only
        }else if(recordIdOfParent.recordTypeid  == idLevel1.Id){
            w.recordTypeid = idLevel2.Id;
        }else if(recordIdOfParent.recordTypeid  == idLevel0.Id){
            w.recordTypeid = idLevel1.Id;
        }
        update w;
    }
}
}
Hello,

My custom object has few columns,
When i try to reset recordTypeid t gives me //record is read only

I dont know the cause for this error.

I am able to update other rows with other fields.

I have trouble in updating current row with column recordTypeid 
Best Answer chosen by Simrin
ManojjenaManojjena
Hi Simrin ,

Why you are getting this error because after event the record is saved to data base so you need to query with the recor did to the DML else it will throw you error like record is read only .

Second thing in your code you have written some SOQL inside foe loop which is not best practice as we have 100 SOQL limit per execution once you will update more than 100 record it will throw error if you have only one SOQL inside .

Try with below code it  will help !!
 
trigger UsableUpdateTrigger on EFX_WorkItem__c (after insert, after update, after delete) {
   List<EFX_WorkItem__c > efxListToUpdate=new List<EFX_WorkItem__c >();
   Map<String,Id> recNameIdMap=new Map<String,Id>();
   Map<Id,Id> parentIdWithRecTypeIdMap=new Map<Id,Id>();
   for(RecordType recType :[SELECT id,Name FROM RecordType WHERE  SobjectType='EFX_WorkItem__c']){
      recNameIdMap.put(recType.Name,recType.Id);
   }
   Set<Id> parentIdSet=new Set<Id>();
   if(Trigger.isUpdate){
	   for (EFX_WorkItem__c w: trigger.new) {
	      parentIdSet.add(w.Parent_Item__c);
	   }
	   For(EFX_WorkItem__c exw:[SELECT id,RecordTypeId FROM EFX_WorkItem__c WHERE Parent_Item__c IN : parentIdSet]){
	      parentIdWithRecTypeIdMap.put(exw.Id,exw.RecordTypeId);
	   }
	   for(EFX_WorkItem__c exwrk: [SELECT id,Parent_Item__c,RecordTypeId IN : trigger.new]){
	     if(exwrk.Parent_Item__c != null){
		    if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c) != null){
				if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c) == recNameIdMap.get('Level 3 Task')){
				}else if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c)  == recNameIdMap.get('Level 2 Task')){
					exwrk.recordTypeid = recNameIdMap.get('Level 3 Task');  
				}else if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c)  == recNameIdMap.get('Level 1 Task')){
					exwrk.recordTypeid = recNameIdMap.get('Level 2 Task');
				}else if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c)  == recNameIdMap.get('Level 0 Task')){
					exwrk.recordTypeid =recNameIdMap.get('Level 1 Task');
				}
			}
		 }
		  efxListToUpdate.add(exwrk);
	   }
    }
	try{
	  update efxListToUpdate
	}Catch(DmlException de ){
	  System.debug(de);
	}
}

Also you can remove other events as you are using only after update .

Let me know if it helps .

Thanks 
Manoj

All Answers

Mohit Bansal6Mohit Bansal6
Hi Simrin

It is giving you this error because as per Salesforce Limitation, you cannot update the same record in After Trigger.

Secondly, as you having update statement inside the for loop, this is also not a best practices as per salesforce.

Below is updated code:
 
trigger UsableUpdateTrigger on EFX_WorkItem__c (after insert, before update, after delete) {
for (EFX_WorkItem__c w: trigger.new) {
if(Trigger.isUpdate){
    EFX_WorkItem__c recordIdOfParent = [SELECT recordTypeid FROM EFX_WorkItem__c WHERE Parent_Item__c =:w.Parent_Item__c limit 1];
    RecordType idLevel0 = [Select Id From RecordType Where Name ='Level 0 Task' limit 1];
    RecordType idLevel1 = [Select Id From RecordType Where Name ='Level 1 Task' limit 1];
    RecordType idLevel2 = [Select Id From RecordType Where Name ='Level 2 Task' limit 1];
    RecordType idLevel3 = [Select Id From RecordType Where Name ='Level 3 Task' limit 1];
    if(recordIdOfParent!=null){
        if(recordIdOfParent.recordTypeid == idLevel3.Id){
        }else if(recordIdOfParent.recordTypeid  == idLevel2.Id){
            w.recordTypeid = idLevel3.Id;  //record is read only
        }else if(recordIdOfParent.recordTypeid  == idLevel1.Id){
            w.recordTypeid = idLevel2.Id;
        }else if(recordIdOfParent.recordTypeid  == idLevel0.Id){
            w.recordTypeid = idLevel1.Id;
        }
    }
}

}

Try this code and i am sure, it will resolve your issue.

Regards
Mohit Bansal

In case, you face any issue, drop me message on forum or Skype me @mohit_bansal17, if you need any help.


Please mark this as solution by selecting it as best answer if this solves your problem, So that if anyone has this issue this post can help
ManojjenaManojjena
Hi Simrin ,

Why you are getting this error because after event the record is saved to data base so you need to query with the recor did to the DML else it will throw you error like record is read only .

Second thing in your code you have written some SOQL inside foe loop which is not best practice as we have 100 SOQL limit per execution once you will update more than 100 record it will throw error if you have only one SOQL inside .

Try with below code it  will help !!
 
trigger UsableUpdateTrigger on EFX_WorkItem__c (after insert, after update, after delete) {
   List<EFX_WorkItem__c > efxListToUpdate=new List<EFX_WorkItem__c >();
   Map<String,Id> recNameIdMap=new Map<String,Id>();
   Map<Id,Id> parentIdWithRecTypeIdMap=new Map<Id,Id>();
   for(RecordType recType :[SELECT id,Name FROM RecordType WHERE  SobjectType='EFX_WorkItem__c']){
      recNameIdMap.put(recType.Name,recType.Id);
   }
   Set<Id> parentIdSet=new Set<Id>();
   if(Trigger.isUpdate){
	   for (EFX_WorkItem__c w: trigger.new) {
	      parentIdSet.add(w.Parent_Item__c);
	   }
	   For(EFX_WorkItem__c exw:[SELECT id,RecordTypeId FROM EFX_WorkItem__c WHERE Parent_Item__c IN : parentIdSet]){
	      parentIdWithRecTypeIdMap.put(exw.Id,exw.RecordTypeId);
	   }
	   for(EFX_WorkItem__c exwrk: [SELECT id,Parent_Item__c,RecordTypeId IN : trigger.new]){
	     if(exwrk.Parent_Item__c != null){
		    if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c) != null){
				if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c) == recNameIdMap.get('Level 3 Task')){
				}else if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c)  == recNameIdMap.get('Level 2 Task')){
					exwrk.recordTypeid = recNameIdMap.get('Level 3 Task');  
				}else if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c)  == recNameIdMap.get('Level 1 Task')){
					exwrk.recordTypeid = recNameIdMap.get('Level 2 Task');
				}else if(parentIdWithRecTypeIdMap.get(exwrk.Parent_Item__c)  == recNameIdMap.get('Level 0 Task')){
					exwrk.recordTypeid =recNameIdMap.get('Level 1 Task');
				}
			}
		 }
		  efxListToUpdate.add(exwrk);
	   }
    }
	try{
	  update efxListToUpdate
	}Catch(DmlException de ){
	  System.debug(de);
	}
}

Also you can remove other events as you are using only after update .

Let me know if it helps .

Thanks 
Manoj
This was selected as the best answer