+ Start a Discussion

Why does this trigger only fire *SOMETIMES* in Production????

I've written the trigger that I'm including below. 
The trigger looks for when an account owner has been changed, and then calls up the related contacts and assigns the new account owner as the owner of all contacts.
trigger accountUpdateContactOwner on Account (after update) {

// first Id is Account.Id, second Id is Account.OwnerId

Map<Id, Id> AcctOwners = new Map<Id, Id>();
// loop through and for each account, put its Id and its OwnerId in the map                 
 for (Integer i = 0; i < Trigger.new.size(); i++)
  if (Trigger.old[i].OwnerId != Trigger.new[i].OwnerId ) {

// for each account in the map, find the contacts and loop through them to 
// reassign the OwnerId
 for (Contact updContact : [select Id, AccountId, OwnerId from Contact
       where AccountId in :AcctOwners.keyset() limit  999 ])
    updContact.OwnerId = AcctOwners.get(updContact.AccountId);


The problem is that I tested it to death before deploying it to production.  If the trigger just didn't work at all, I woudln't think it strange.  The fact that it only works for certain accounts and not for others, and only in production, is really baffling.
Sadly, I asked Salesforce.com for support, and while they did look at and test my code, they refused to support me and told me I'd have to use discussion boards instead.
The process:  Wrote it in development org, wrote unit test, got 100% coverage.  Began tests.  Loaded thousands of test accounts and contacts.  Assigned 2000 contacts to an account, used the UI to make changes, trigger ran, all changes made beautifully.  Did the same, but assigned one contact to 2000 accounts, changed owner through the UI (250 at a time), they all worked.  Repeated the tests through the Data Loader.  Got errors due to limits.  Reworked the code to its present form above, re-ran lots of Data Loader tests mirroring what I'd done through the UI and they all worked wonderfully.
I deployed the code to Production and it seemed to work there, but after watching it for a couple days using reports, I found that the trigger was firing only sometimes.
I put a ticket in with Salesforce.com support so they can explain why triggers only fire sometimes.  I thought either they work or they don't work, right??  I gave them two account examples to try.  The first example had 10 contacts and the trigger works.  The second example had one contact which didn't work.  Then I found about 1000 other examples, most but not all were modified through the data loader.  I thought it was just for large accounts with lots of contacts maybe hitting a limit or something, but most of these accounts had one or two contacts.
How do things work so nicely in development, but not work in production?

Message Edited by RDN_LHR on 12-09-2008 02:37 AM

Message Edited by RDN_LHR on 12-09-2008 02:40 AM

Message Edited by RDN_LHR on 12-09-2008 02:44 AM

Message Edited by RDN_LHR on 12-10-2008 09:12 AM
This may or may not help. I had a similiar issue where triggers appeared not to be firing. I found that the trigger was actually firing - but not accomplishing the task I had in mind. A few things that happened in my case:
1. Ownership issues - Sometimes the object being updated is owned by someone other than the user causing the trigger to fire. This prevented the trigger from editing (permission issue)
2. After Update vs Before Update - other people may be able to talk about this with more expertise than me. I've noticed that I have more success editing records using Before Update than After Update. In your situation an After Update makes sense since you're editing records - other than the one firing the trigger
3. Not updating the array. Sometimes I forget to put Update ArrayName (in your case Update updContact; ). When I've done this I noticed that sometimes my records got  updated and sometimes they didn't.
Not sure if any of these are your issues though. If I had to guess, I would think Ownership/Permission issues may be a cause. Have you noticed any patterns between the records that work vs the records that do?
You update the contact object, but never call update, so the contact records in the DB will never get updated.
If it were a case of calling update, why does this trigger always work in a development org and in a production org, work on some accounts but not all accounts?
That is the big mystery for this particular one -- the fact that it works all the time in development and sometimes in production.  Is it really just a case of updating the array?  And if it requires that, why does it still work when it's not there?

Message Edited by RDN_LHR on 12-10-2008 02:14 AM
Thanks for this response.  It brings up another question ... I basically want this trigger to fire and the records to update regardless of the permissions of the user who's editing the record at the time it updates.   Is there something extra I have to add to make that happen?
I can guarantee that the code you posted does not work anywhere.
Thanks for the "guarantee", Simon, for what it's worth.
Anyone else who thinks I'm making this up can have the username and password to my development account to show that it does work as I've said. 
If anyone has answers to this, I'd appreciate them.
The code you posted (are you 100% sure the code you posted at the start of the thread is exactly what you have?) is an after update trigger, so no changes you make to an apex object instance will be applied to the DB, unless you call insert or update. your code never calls insert or update.

If you have an account where you see some expected behavior, then its because something else is doing it, this trigger code is not. Do you have a system log from a test where you see the expected behavior? what do you unit tests look like?
When you change account ownership through the UI, it automatically transfers contacts, as detailed on the ownership edit page.

This screen allows you to transfer an account from one user to another. When you transfer ownership of an account, the new owner will also gain ownership of the following records related to the transferred account:
all notes and open activities for this account owned by you
all contacts within the account owned by you, including all related notes and open activities owned by you
all opportunities (including closed opportunities if you select the Transfer closed opportunities checkbox below) within the account owned by you, including all related notes and open activities owned by you

So when you were testing, what you thought was behavior coming from your trigger is actually the built in behavior of the ownership change UI page.
I'll take a look at all this and write a different unit test.