function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Derek M HughesDerek M Hughes 

Error in trigger only from an update via a site - lazy compilation?

This one took countless hours to isolate and even then I battle to accept the conslusion I have reached.

Scenario:
1. We have a trigger on Opportunity that posts a FeedItem to a specific Chatter group when an Opportunity is Closed Won - a digital reining of the bell. We set the CreatedBy field on the new FeedItem to a specific userid so the post comes from that user.
2. When Opps are updated by normal users this trigger works like a bomb and the Chatter post lets the whole sales team know about the win.  The post is seen to come from the designated user
3. We have a site where customers can place an order online which created a new Opportunity of a specific record type in the controller and then updates that Opportunity to Closed Won.  The traigger is written to ignore these online closed won opportunities and not post to Chatter, but of course the trigger is still called.

The Problem:
The creation of the opportunity through the controller from the site fails itermittently.  The failure is in the trigger and the message is "Field is not writeable: FeedItem.CreatedById".  The line of code in the trigger is not being executed as the opportunity does not meet the criteria and a FeedITem is not created.

The Debug Log:
This doesn't shed any light on the problem as it simple ends at the "insert newOpportunity;" statement and does not show any of the execution in the trigger.  It is as if the code hit a brick wall and just stopped.

The Problem:
After many, many hours of painstaking trial and error, debugging, changing permissions and more we were still gettting this error ittermitently. FInally I spotted a pattern. The times that it worked through the site controller was when there had been an opportunity updated recently by a normal user (< a few minutes before the udpate from the site).  So after a successful update by an nromal user there is a window in whcih updates from the site go through.

The Cause?
Could it be that the trigger is compiled on demand when the internal user updates an opp, is then held in a cache for a while and if the site does an updated while it is cached it works?  After some time has elapsed the compiled trigger it purged and if the site then tries an update it fails due to the running user "Site Guest User" during compilation?

I would love some input on this.  Obviously a solution would be great but I wonder if anyone else has ever had a similar issue?

Regards

Derek

 

Derek M HughesDerek M Hughes
PS: This error only occurs in PRODUCTION, we are unable to re-create it in our sandbox.  Maybe that is also a clue?
Krishna SambarajuKrishna Sambaraju
Can you share the trigger?
Derek M HughesDerek M Hughes

HI,

I have removed some other logic not related to the use case at hand, and stripped of some error handling for ease of reading.

REgards

Derek

trigger Opportunity_Trigger on Opportunity (after delete, after insert, after undelete, 
after update, before delete, before insert, before update) 
{
     
    if(Trigger.isAfter && (Trigger.isUpdate || Trigger.isInsert))
     {
        List<FeedItem> posts = new List<FeedItem>();
        List<Opportunity> updatedOpps = 
        [
            SELECT 
                Id,
                Name, 
                Account.Name, 
                Owner.Name, 
                Amount, 
                IsWon, 
                Type,
                Business_Unit__c,
                CurrencyIsoCode 
            FROM 
                Opportunity 
            WHERE 
                Id IN :Trigger.newMap.keySet() AND 
                IsWon = true AND
                RecordType.DeveloperName != 'Training_Booking'
            
        ];
        
        system.debug('OpportunityTrigger: updatedOpps: '+updatedOpps);
        
        list<User> users = [SELECT Id, Name FROM User WHERE Alias = 'sysadmin'];
        
        Id UserId;
            
        list<CollaborationGroup> chatterGroups = [SELECT Id FROM CollaborationGroup WHERE Name like 'Ring The Bell%'];
        system.debug('chatterGroups: '+chatterGRoups);
        
        if (chatterGroups.size() > 0)
        {
            for (Opportunity opp : updatedOpps) {
                if (opp.isWon && !trigger.oldMap.get(opp.Id).isWon )
                {
                    if (users.size() == 0 )
                        UserId = UserInfo.getUserId();
                    else
                        UserId = users[0].Id;

                    String symbol = opp.CurrencyIsoCode == 'ZAR' ? 'R' : opp.CurrencyIsoCode ;
                    String amnt = symbol+opp.Amount.round().format();
                    
                    String status = opp.Owner.Name + ' just won a '+opp.type+' deal (' + opp.name +') at ' + 
                        opp.Account.Name + ' for the '+ opp.Business_Unit__c + ' practice' + 
                        (opp.Amount > 5000 ? ', for ' + amnt : '') + '. Congratulations!';
                        
                    FeedItem post = new FeedItem
                    (
                        CreatedById = UserId,  //TEMP REMOVE TO STOP ISSUE ON SITE UPDATE
                        ParentId = chatterGroups[0].Id,
                        Title = opp.Name,
                        Body = status
                    );
                system.debug('post: '+post);
                posts.add(post);
                }
            }
            insert posts;    
        }
    }    
}

Krishna SambarajuKrishna Sambaraju
Did you try checking the size of the posts before inserting.
if (posts.size() > 0)
{
	insert posts;
}
Derek M HughesDerek M Hughes

No.  I have not tried that, but will to cover all my bases.  Although I doubt it will make difference as I dont believe the triggers is getting executed at all.   I did find this very informative blog post by Alex Berg (https://www.sundoginteractive.com/sunblog/posts/salesforces-apex-runtime-design-old-vs-new) which seems to confirm my suspicions that its a compile error which only happens when there is not a cached compiled version available and the running use is the site guest user!
Brooke BakerBrooke Baker
Hi Derek,
I have exactly the same problem. I have spent hours trying to get around it and no joy. Did you have any luck finding a solution or work around?

Cheers,
Brooke