Stop a trigger calling itself
Debug it · Advanced · 15 min · Runs in your Salesforce Developer org · Apex Path
Scenario. Since a new handler went live, agents cannot close a Case. The error says maximum trigger depth exceeded, and nobody has changed the trigger.
Closing one Case now fails with maximum trigger depth exceeded. The after-update handler updates the Case, which runs the handler again. Break the loop.
What you will learn
maximum trigger depth exceeded means a trigger caused DML that ran the same trigger, again and again, sixteen times. Here the after-update handler updates the Case it was called for, so the update runs it again.
Two fixes work. A static Set remembers the Ids handled in this transaction:
private static Set<Id> handledIds = new Set<Id>();
Or act only when Status changed to Closed, using oldMap.
Gotcha. A static Boolean also blocks every later record. Track Ids.
The task
Fix the handler so each Case closed in a transaction is marked exactly once, and the follow-up update does not run the handler's work again.
Examples:
- Case Status
New→Closed: Description becomesClosed by the handler - Case Status
New→Working: Description stays as it was - 200 Cases closed together → each marked once, with one follow-up update
Requirements:
- Only act on Cases whose Status is
Closed. - Stop the second run. Either skip Ids already in a static
Set<Id>, or skip Cases whose old Status inoldMapwas alreadyClosed. - Keep one follow-up update for the whole list, after the loop.
- Do not change the marker text.
Starter code
public class AS_AFE55B6263D0_CaseCloser {
public static void afterUpdate(List<Case> cases, Map<Id, Case> oldMap) {
List<Case> followUps = new List<Case>();
for (Case caseRecord : cases) {
if (caseRecord.Status == 'Closed') {
followUps.add(new Case(
Id = caseRecord.Id,
Description = 'Closed by the handler'
));
}
}
if (!followUps.isEmpty()) {
update followUps;
}
}
}
When it passes
Closing a Case marks it once and never loops. Other Status changes do nothing. 200 Cases closed together cost the same DML as one.
You write the Apex yourself. ApexSensei runs it and tells you what passed and what did not.