I have a scenario where i have a checkbox field on Account object "test_check__c" and this checkbox field is applicable only for child accounts and not for the parent.

Scenario is : - Parent account can have only 1 child with the above checkbox as checked. Means there wont be any case where there will be 2 child with "test_check__c" as checked.

Below is the code which i am trying

trigger AccountTrigger on Account (after update) {

    set<Id> accPId = new set<Id>();
    set<Id> accId = new set<Id>();
    List<Account> lstToUpdate = new List<Account>();

    for(Account acc: trigger.new) {
        Account oldacc  = trigger.oldMap.get(acc.Id);
        if(acc.ParentId != oldacc.ParentId && oldacc.ParentId == null) {
            if(acc.test_check__c !=  oldacc.test_check__c) {
    List<Account> lstacc = [SELECT Id,Name, test_check__c from Account where Id NOT IN:accId AND ParentId IN: accPId AND test_check__c = true];
    for(Account a: lstacc) {
        a.test_check__c = false;
    update lstToUpdate;

the issue which i am encountering is if i check the first child as true its working fine as below

enter image description here

But when i try to make another child "test_check__c" as true, all the child's field is becoming as false

enter image description here

i am seeing some recursive behaviour is happening here.

2 Answers 2


You don't need recursion blocking, you need a better algorithm. Here's an implementation that should work:

trigger q367640 on Account (after update) {
    Set<Id> parentIds = new Set<Id>();
    // Records to Update
    Account[] recordsToUpdate = new Account[0];
    // Records that we need to process in second loop
    Account[] testCheckAccounts = new Account[0];
    // Extract parent Ids
    for(Account record: Trigger.new) {
        if(record.Test_Check__c && record.ParentId != null) {
    // Nothing to do here
    if(parentIds.isEmpty()) {
    // Keep parent Ids with more than one child checked
    parentIds.retainAll(new Map<Id, AggregateResult>([
        SELECT ParentId Id
        FROM Account
        WHERE ParentId = :parentIds
        AND Test_Check__c = true
        GROUP BY ParentId
        HAVING COUNT(ParentId) > 1
    // Nothing to do here
    if(parentIds.isEmpty()) {
    // Track checked records in this trigger context
    Map<Id, Id> parentChildChecked = new Map<Id, Id>();
    for(Account record: testCheckAccounts) {
        // More than one child in this transaction is already checked
        if(parentIds.contains(record.ParentId) && 
           parentChildChecked.put(record.ParentId, record.Id) != null) {
               recordsToUpdate.add(new Account(Id=record.id, Test_Check__c=false));
    // Get child records for parents that have more than two checked records and not in this trigger context
    for(Account record: [SELECT Id FROM Account WHERE ParentId = :parentIds AND Test_Check__c = true AND Id NOT IN :testCheckAccounts]) {
        recordsToUpdate.add(new Account(Id=record.Id, Test_Check__c=false));
    update recordsToUpdate;

I made it work adding a recursive class into the trigger

public class RecursiveTriggerHandler{
     public static Boolean isFirstTime = true;
  • Thats what needs to be done to handle recursive....Good
    – Mohit K
    Commented Jan 23, 2022 at 8:57
  • A simple static boolean is a poor choice for recursion handling. It'll cause whatever code it's "protecting" to only run for the first trigger chunk (the first 200 records). At the very least (for everything that isn't before insert), you should use a static Set<Id> for recursion prevention.
    – Derek F
    Commented Jan 23, 2022 at 13:28
  • @DerekF Or, as is so often the case, write the algorithm such that it does not need a recursion block at all.
    – sfdcfox
    Commented Jan 23, 2022 at 15:00

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .