Duplicate indicator results are getting created when indicator task closed

harinya
Tera Contributor

Hi ,

I’m facing an issue in ServiceNow GRC where duplicate Indicator Results are being created for the same Indicator Task when the state changes to Closed.

Ideally, it should create only one Indicator Result per task, so I wanted to check if this is expected OOTB behavior or not. If it is, could you please suggest how we can minimize or prevent duplicate creation?

Appreciate any guidance on this. Thanks in advance!



1 REPLY 1

Naveen20
ServiceNow Employee

 

Not OOTB behvior. The platform is designed to create one Indicator Result per Indicator Task upon closure. However, duplicates typically arise due to one of these scenarios:

  1. Multiple Business Rules firing on state change — The OOTB Business Rule that generates the Indicator Result (usually something like "Create Indicator Result" on the sn_grc_indicator_task table) can fire more than once if there are additional custom or OOTB Business Rules updating the same record during the same transaction, causing the state-change condition to re-evaluate.

  2. Recursive updates — If a Business Rule or Flow on the Indicator Task record triggers an update() call on the same record after it transitions to Closed, the "insert" logic for the Indicator Result may execute again during that second pass.

  3. Async + sync overlap — If both a synchronous BR and an asynchronous Flow/Workflow are configured to create the result on the same state transition, you'll get two.

How to diagnose it:

  • Check the sys_trigger and transaction logs around the time of closure to see if the task is being updated multiple times in quick succession.
  • Review all Business Rules on sn_grc_indicator_task that run on update with a condition referencing state changes to Closed. Look for both the OOTB rule and any custom ones.
  • Check Flow Designer — sometimes a parallel Flow is also listening for the same state change.

How to prevent duplicates:

Here are a few approaches, roughly in order of preference:

The cleanest fix is to add a guard condition on the Business Rule (or Flow) that creates the Indicator Result. Before inserting, do a GlideRecord query to check if an Indicator Result already exists for that Indicator Task:

// Inside the BR that creates the Indicator Result
var gr = new GlideRecord('sn_grc_indicator_result');
gr.addQuery('indicator_task', current.sys_id);
gr.query();

if (!gr.hasNext()) {
    // Safe to create the result
    var result = new GlideRecord('sn_grc_indicator_result');
    result.initialize();
    result.indicator_task = current.sys_id;
    // ... populate other fields
    result.insert();
}

If you don't want to modify the OOTB BR directly (best practice in scoped apps), you can instead create a before-insert Business Rule on sn_grc_indicator_result that aborts the insert if a duplicate already exists:

// Before Insert BR on sn_grc_indicator_result
(function executeRule(current, previous) {
    var gr = new GlideRecord('sn_grc_indicator_result');
    gr.addQuery('indicator_task', current.indicator_task);
    gr.setLimit(1);
    gr.query();

    if (gr.hasNext()) {
        current.setAbortAction(true);
        gs.info('Duplicate Indicator Result prevented for task: ' + current.indicator_task);
    }
})(current, previous);

This second approach is less invasive since it doesn't touch the OOTB creation logic — it just acts as a safety net.