i wrote a function inside event trigger handler that should receive custom times for a meeting, a custom time zone of the customer, and a timezone for the user - and calculate the time of the meeting according to the user's timezone.

for example:

Customer_Time_Zone__c : GMT -5

User's Time Zone: GMT + 2

Start_Customer_Time_Zone__c : 10:00am

End_Customer_Time_Zone__c: 11:00am

The function will receive this data and calculate that the standard time of the meeting is 17:00pm-18:00 in the user's timezone, and fill the event standard time fields StartDateTime, EndDateTime.

The problem is: i can't do that, because the fields are read only. i have no idea how to update these fields, and if there are more fields that are related to them such as duration etc.

Here is the function so far:

private static void updateStandartDateTimeFields(User u, Event e)
        System.debug('updateStandartDateTimeFields start');
        System.debug('User: ' + u);
        System.debug('Event: ' + e);

        e.StartDateTime = e.Start_Customer_Time_Zone__c;
        e.EndDateTime = e.End_Customer_Time_Zone__c;

        Update e;

When I run a test I receive the following error:

System.DmlException: Insert failed. First exception on row 0; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, EventTrigger: execution of AfterInsert
caused by: System.FinalException: Record is read-only

Class.EventTriggerHandler.updateStandartDateTimeFields: line 131, column 1
Class.EventTriggerHandler.createMeeting: line 59, column 1
Class.EventTriggerHandler.afterInsert: line 31, column 1
Class.TriggerHandler.run: line 45, column 1
Trigger.EventTrigger: line 13, column 1: []

Can I avoid this error? If so, how?

  • 1
    Looks like you have your trigger on after insert and after update events. Why don't you perform the update on before events? – Raul Jun 26 '17 at 11:22
  • I have to do it on after update for other reasons. is there a way i can do this in after update? – Dana Griff Jun 26 '17 at 11:36
  • You should really clarify those "other reasons" because there's probably a different way to handle them. – Adrian Larson Jun 26 '17 at 11:38
  • not reasons i'm aware of, its a code of other developers, i just know that it has to occure in "after update" – Dana Griff Jun 26 '17 at 11:46
  • @D.Griff Well you should push back on them to provide better justification. Doing a field update in an after context clearly violates Salesforce's own recommendations on trigger best practice. – Adrian Larson Jun 26 '17 at 13:23

Field updates belong in a before trigger and do not require additional DML operations. I suggest you have a read of Triggers from the Apex Developer Guide:

You can define triggers for top-level standard objects that support triggers, such as a Contact or an Account, some standard child objects, such as a CaseComment, and custom objects. To define a trigger, from the object management settings for the object whose triggers you want to access, go to Triggers.

There are two types of triggers:

  • Before triggers are used to update or validate record values before they’re saved to the database.
  • After triggers are used to access field values that are set by the system (such as a record's Id or LastModifiedDate field), and to affect changes in other records, such as logging into an audit table or firing asynchronous events with a queue. The records that fire the after trigger are read-only.

If you really must use an after context, you can't operate on the context records, but rather must create new ones.

List<Event> toUpdate = new List<Event>();
for (Event record : trigger.new)
    toUpdate.add(new Event(Id=record.Id, /*other data*/));
update toUpdate;
  • Having a check for Recursive Trigger Calls is nice to have/necessary. – Raul Jun 26 '17 at 12:59
  • 1
    Well... not if you use before events but yeah you are right. Although I find appropriate filters to do the job 99% of the time. – Adrian Larson Jun 26 '17 at 13:08

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.