Business rule generating duplicate event entries

matthew_hughes
Kilo Sage

I'm trying to generate emails based on the below business rules that will trigger two events:

matthew_hughes_0-1746530970226.png

 

I'm using the below script:

(function executeRule(current, previous /*null when async*/) {
    // Arrays to track processed emails and SYS IDs
    var processedEmails = [];
    var processedSysIds = [];

    // Function to trigger event if email and SYS ID are not already processed
    function triggerEvent(eventName, email, sysId, manager) {
        if (processedEmails.indexOf(email) === -1 && processedSysIds.indexOf(sysId) === -1) {
            gs.info("gs.eventQueue('" + eventName + "', " + current + ", " + email + ")");
            gs.eventQueue(eventName, current, email, manager);
            processedEmails.push(email);
            processedSysIds.push(sysId);
        }
    }

    if (current.state == 'pending_recertification') {
        var managerEmail = current.group_manager.email;
        var lineManagerEmail = current.group_manager.manager.email;
        var managerSysId = current.group_manager.sys_id;
        var lineManagerSysId = current.group_manager.manager.sys_id;

        gs.info('MH - managerEmail ' + managerEmail);
        gs.info('MH - lineManagerEmail ' + lineManagerEmail);
        gs.info('MH - managerSysId ' + managerSysId);
        gs.info('MH - lineManagerSysId ' + lineManagerSysId);

        // Trigger events for managerEmail and lineManagerEmail
        triggerEvent('x_lbg_group_recert.lbg.group.recert.grou', managerEmail, managerSysId, current.group_manager);
        triggerEvent('x_lbg_group_recert.lbg.group.recert.line', lineManagerEmail, lineManagerSysId, current.group_manager.manager);
    }
})(current, previous);
 
However, what I've noticed is that it's triggering the same events more than once when it should appear once if the user's email and sys ID already appears:
matthew_hughes_1-1746531083978.png

 

 

5 REPLIES 5

_ukasz Rybicki
Giga Guru

Summary

The duplicate events issue stems from an After Update Business Rule that queues emails twice: once because in-memory arrays reset on each execution, and again if another script calls current.update(), retriggering the rule (ServiceNow)(ServiceNow). Replacing array-based tracking with a GlideRecord query against Event [sysevent] ensures idempotency by checking for existing events before queuing new ones (ServiceNow). As a no-code alternative, configure two out-of-the-box Notifications on the same table to fire on state change, which inherently prevents duplicate sends per transition (ServiceNow)(ServiceNow).

Problem Identification

  • Arrays reset per execution: The original script uses processedEmails and processedSysIds arrays that are reinitialized on every BR run, so they don’t persist between invocations (ServiceNow).

  • Recursive BR firing: A call to current.update() elsewhere can cause the rule to execute twice for the same record, duplicating events (ServiceNow)(support.servicenow.com).

  • Missing state-change guard: Without using current.state.changesTo('pending_recertification'), events fire on both initial load and subsequent updates (ServiceNow).

Proposed Solutions

1. Code-Based GlideRecord Deduplication

  1. Business Rule Setup

    • Table: x_lbg_group_recert

    • When: After → Update

    • Condition: state.changesTo('pending_recertification') (ServiceNow)(ServiceNow)

  2. Script

    (function executeRule(current, previous) {
      function triggerEvent(name, email, mgr) {
        var gr = new GlideRecord('sysevent');
        gr.addQuery('name', name);
        gr.addQuery('instance', current.sys_id);
        gr.addQuery('parm1', email);
        gr.query();
        if (!gr.next()) {
          gs.eventQueue(name, current, email, mgr);
        }
      }
      if (current.state.changesTo('pending_recertification')) {
        triggerEvent(
          'x_lbg_group_recert.lbg.group.recert.grou',
          current.group_manager.email,
          current.group_manager
        );
        triggerEvent(
          'x_lbg_group_recert.lbg.group.recert.line',
          current.group_manager.manager.email,
          current.group_manager.manager
        );
      }
    })(current, previous);
  3. Best Practices & Notes

    • Avoid current.update() in After BRs to prevent recursion (ServiceNow).

    • No arrays: GlideRecord checks guarantee one event per record per manager (ServiceNow).

2. No-Code OOTB Notifications

  1. Notification 1

    • Table: x_lbg_group_recert

    • Trigger: When “State changes to pending_recertification”

    • Recipient: Group Manager (group_manager)

  2. Notification 2

    • Same trigger conditions

    • Recipient: Line Manager (group_manager.manager)

  3. Advantages

    • Zero scripting required; built-in engine prevents duplicate sends per transition (ServiceNow).

    • Easily visible and maintainable via the UI (ServiceNow).

Testing

  1. Change a record’s state to pending_recertification in a sub-production instance.

  2. Code-Based: Verify exactly two entries in Event [sysevent] matching your instance and parm1 values.

  3. Notifications: Confirm two emails—one to each manager—are sent only once per transition.

Sources

  1. Business rule generating duplicate event entries – ServiceNow Community – Describes the original duplicate email triggers (ServiceNow)

  2. Duplicate CI Monitoring records – ServiceNow Community – Explains BR firing twice due to current.update() (ServiceNow)

  3. How to prevent duplicate user records – ServiceNow Community – Demonstrates GlideRecord dedup in BR (ServiceNow)

  4. Double update occurs in Inbound Actions – ServiceNow Support KB0824467 – Highlights recursion from multiple updates (support.servicenow.com)

  5. Avoid duplicate entry by BR – ServiceNow Community – Confirms GlideRecord check approach (ServiceNow)

  6. changesTo() function not working – ServiceNow Community – Validates proper changesTo usage (ServiceNow)

  7. Using current.update() in After BR – ServiceNow Community – Advises against current.update() in After BRs (ServiceNow)

  8. Business Rules Technical Best Practices – ServiceNow Developers – Recommends idempotent script design (Developer Portal)

  9. Notifications reference – ServiceNow Documentation – How to configure Notifications for record changes (ServiceNow)

  10. Create custom notifications – ServiceNow Documentation – No-code setup for Notifications after record changes (ServiceNow)

Please mark this as the correct answer! 😊