Workflow loops not working

Hello Community,

I am implementing a workflow to iterate over a list of users. The users are taken from the “HTTP Request” action over the “List Governance Group Members” API.
The action is correctly configured and returns the correct data in an array.
I need loop over the body of the response and operate on its elements.
The loop is configured as follows:

  • Loop input: $.hTTPRequest.body
  • Context: $
    You can double check it on this screenshot:

When I test the workflow, however, it fails and the Loop never iterate over the elements. By checking the test data this is what I see:

HTTP Request action > Step Output:

{
  "body": [
    {
      "email": "[email protected]",
      "id": "086da00565bd48cdb2061b92a6b47ac4",
      "name": "L---- P--------",
      "type": "IDENTITY"
    },
    {
      "email": "[email protected]",
      "id": "60e744fd3917488682b6e2a3b134c46b",
      "name": "M---- C---------",
      "type": "IDENTITY"
    }
  ],
  "headers": {},
  "responseTime": "0.419180 seconds",
  "statusCode": 200
}

You can see from the output above that the response is correct and the body is an array of 2 elements.

Let’s have a look to the Loop Operator instead with particular focus on its loopInput:
Loop Operator > Step Output:

{
  "context": {... },
  "definitions": {...},
  "payloads": [
    {
      "loopInput": {
        "email": "[email protected]",
        "id": "086da00565bd48cdb2061b92a6b47ac4",
        "name": "L----- P-------",
        "type": "IDENTITY"
      }
    },
    {
      "loopInput": {
        "email": "[email protected]",
        "id": "60e744fd3917488682b6e2a3b134c46b",
        "name": "M---- C--------",
        "type": "IDENTITY"
      }
    }
  ]
}

The loopInput is present twice and it holds the correct values and elements.
I tried multiple times but it never proceeds with the loop iterations.

This is how the loop appears during the test:


The actions before and after the loop are executed correctly.

Why the loop doesn’t iterate over its elements?
Any information could help me a lot!

Thank you

When I test my workflows, the display on screen doesn’t show that the contents of the loop are iterated over. However, they actually are executed. Is it possible that the loop is working and you’re just not seeing the results on-screen?

I thought about that and tried the workflow but it fails

I created a similar workflow and loop ran successfully twice as there were 2 members in the governance group I tested. I received 2 emails sent from inside the loop

Could you share the details on loopid and comparison operators inside the loop?

Not directly related to your question, but just want to point this out in case it matters to you:

The loop implementation by SailPoint is essentially spraying each iteration into parallel sub-workflows of no more than 250 threads. Which results in a non-deterministic ordering side-effect. (i.e. Workflow loops have three quirks.)

With that, how did you determine " but it never proceeds with the loop iterations."? (Because you also saw the loop inputs have two different values)

What specific “it” is this referring to? A step inside the loop? e.g. “loopid”?

Loop configuration:

The “Value 2” is a variable which holds the value of $.trigger.requestedBy.id
You can check that the “$.defineVariable3.richiedente” is not misspelled by looking at following screenshot: here I am trying to set this variable in place of “Value 1” and I pick it from the dropdown menu.

This is just a doublecheck to verify that nothing is misspelled.
Please also note that the “$.defineVariable3.richiedente” effectively holds the $.trigger.requestedBy.id value during workflow simulations.
Additionally I have also tested the loop comparison between: $.loop.loopInput.id and $.trigger.requestedBy.id but still nothing.

By running the simulation I never get inside the loop. I also tried this by leaving only the “send email” action inside it but it won’t send anything.
If may shed some light on this, the workflow is triggered by the external trigger “Access Request Submitted”, I have subscribed to the trigger and set the “SYNC” response time. Even switching to the “ASYNC” response with 5 minutes timeout doesn’t change anything.

The two input values to the loop are two Identity IDs (i.e. ID0001 and ID0002) and the requester ($.trigger.requestedBy.id) holds the ID of one of the IDs above (i.e. ID0001).

As shown above, after I perform the HTTP Request action I obtain a body with an array of 2 Identities. One of these is the same requester coming from the trigger.
Based on this and the Comparator operator set in the loop I expect it to match once and fail once. I don’t care about the order but my only goal is to fall once in the “True” branch of the comparison

UPDATE: even if loop items do not get highlighted in the canvas, I managed to get inside it. I tested it by setting a “Send Email” action just after entering the loop and before the comparison.
What constantly fails is the String comparator which never ends in the TRUE branch.
In the email sent just at loop start I included in its body the $.loopInput, $.loopInput.id, $.trigger.requestedBy.id and the $.defineVariable3.richiedente variables. You can check the following screenshot as reference of the configuration for the email:

Only the two loop variables get decoded into their values while the other two won’t. This is how they are displayed in the email received:
image

To further check I have also set another “Send Email” action before the loop just by duplicating this action and there I can see the last two variables correctly displayed:

I have then checked once again the loop inputs but nothing changes if I try setting the context to either:

  • $
  • $.defineVariable3.richiedente
  • $.trigger.requestedBy.id

The result in the email is always the same and the “Comparator” operator in the loop never enters the “TRUE” branch.,

What am I doing wrong here?

Inside the loop, it’s a sub-workflow. That sub-workflow has no understanding / visibility to the parent workflow variables other than what you pass to it in the loop input and loop context variable.

i.e. Inside the loop, you can’t refer to $.trigger, nor $.defineVariable3.

Refer to loop context: Operators - SailPoint Identity Services

That is to way, if you will, think of a loop as a function call where you pass loop input and loop context as variables. The function (the loop) only sees loop input and loop context.

Yes but in the loop context I passed $ which should pass the entire list of variables to the loop.
Isn’t this correct? Did I misinterpreted the context?

“The Context field within the loop step allows you to select data from an additional node prior to the loop…”

The keyword there is “additional node”.

Once inside the loop, you need to refer to the loop context as $.loop.context, so, assuming that you passed in the entire $ from parent to child, then really, you should be referring to variable3 as $.loop.context.defineVariable3.richiedente.

The issue with your workflow loops appears to be related to how you’re trying to access the data.

The “Context” field within the loop step requires an additional node before the loop. This means you need to have a previous node that produces the data to be iterated.

Additionally, verify that the previous node is producing a list or array that can be iterated. If you’re using an API or transformation, confirm that the result is a collection.

If you’re using the Search API, ensure you’re properly handling the pagination of results. An alternative is to use the “forEach” function in a script instead of a visual loop, which may offer more control over the iteration.

I am not sure about passing all variables to context using $. Instead you can try passing $.trigger to the context and then use $.loop.context.requestedBy.id to fetch the id value for comparison. I don’t think you need to define a variable as well

THANK YOU!
Maybe I didn’t read too carefully the documentation but I totally missed this! I had to change the Loop Context to “$.defineVariable3.richiedente


Then, inside the loop, in the Comparator Operator I use that context with just “$.loop.context” and it loads the “$.defineVariable3.richiedente” value.

Thank you again