Logic Apps do not provide a native way to detect which specific iteration inside a foreach has failed. There’s no built-in “index tracker” for failures, and using counters can quickly become messy.
So, to solve this, we built a pattern that logs every failed iteration cleanly using only native Logic Apps features, and with a simple Design:

To better understand it, let’s break it down.
📝 One-Minute Brief
Tracking failed iterations inside Logic Apps foreach loops is not straightforward and often leads to complex counter logic. This Friday Fact shows a clean pattern to identify which iterations fail using native Logic Apps features, improving error handling and workflow maintainability.
We begin our workflow Request-Response workflow with a variable that will be responsible to catching our failed iterations.

Then let’s say that we receive an array like this:
[
{ "item": 0 },
{ "item": 2 },
{ "item": 3 },
{ "item": 4 },
{ "item": 5 },
{ "item": 6 },
{ "item": 0 },
{ "item": 8 },
{ "item": 0 },
{ "item": 10 }
]
Instead of looping directly over the array, we use:
range(0, length(triggerBody()))

This gives us full control over the iteration index (0, 1, 2, etc).

Then all we need to do is to force the failure, and to do that we create a Scope Try and inside a Compose with the expression:
div(100, triggerBody()[items('For_each')]?['item'])

This divides by 100 the current item value.
If the value is 0. It throws a division-by-zero error, which is exactly what we want to simulate to test failure scenarios.
Then we add a Scope Catch that will only be triggered if the previous scope fails, and inside the Scope Catch, we log the failure in an Append to array variable using the expressions:
string(add(items('For_each'), 1))
result('Scope_Try')[0]['error']['message']

How does it work?
items(‘For_each’) – Returns the current index of the iteration inside the foreach loop, for example, 0, 1, 2…
add(…, 1) – Adds 1 to the index since iterations on a foreach start on 1 and not on 0
string(…) – Converts the number into a string, to return it properly in the JSON response.
result(‘Scope_Try’)[0][‘error’][‘message’] – Retrieves the exact error message from the failed division.
At the end of the workflow, we add a Response action, with the variable content as a response:

The result of this solution perfectly logs which iterations failed without the need to use a counter to perform it.
{
"failedIterations": [
{
"iteration": "1",
"error": "Unable to process template language expressions in action 'Simulate_division' inputs at line '0' and column '0': 'Attempt to divide an integral or decimal value by zero in function 'div'.'."
},
{
"iteration": "7",
"error": "Unable to process template language expressions in action 'Simulate_division' inputs at line '0' and column '0': 'Attempt to divide an integral or decimal value by zero in function 'div'.'."
},
{
"iteration": "9",
"error": "Unable to process template language expressions in action 'Simulate_division' inputs at line '0' and column '0': 'Attempt to divide an integral or decimal value by zero in function 'div'.'."
}
]
}
Hope you have enjoyed this Friday Fact, and we will see you in the next one!
To lazy to read? We’ve got you covered! Check out our video version of this content!
Hope you find this helpful! If you enjoyed the content or found it useful and wish to support our efforts to create more, you can contribute towards purchasing a Sauron’s Action Figure for Sandro’s son, yep, not for me! 😀