@@ -4840,16 +4840,44 @@ func (v *VM) executeLoopWithQueue(stepID string, taskNode *avsproto.TaskNode, no
48404840 }
48414841
48424842 // Only treat infrastructure failures (queue submit errors, iteration timeouts)
4843- // as a hard step failure. Per-iteration runner errors (e.g. a contract call
4844- // reverting in one iteration of a Loop > ContractRead) are reflected as nil
4845- // entries in the results array — the loop ran to completion, so we preserve
4846- // OutputData and return success so the client can inspect partial results.
4847- // See AvaProtocol/EigenLayer-AVS#511.
4843+ // as a hard step failure.
48484844 if infraFailure && firstError != nil {
48494845 finalizeStep (s , false , nil , firstError .Error (), log .String ())
48504846 return s , firstError
48514847 }
48524848
4849+ // Count successful vs failed iterations to determine step status.
4850+ // Per-iteration runner errors (e.g. a contract call reverting) are reflected
4851+ // as nil entries in the results array. The loop ran to completion, so we
4852+ // always preserve OutputData for the client to inspect partial results.
4853+ // See AvaProtocol/EigenLayer-AVS#511.
4854+ iterationFailCount := 0
4855+ for _ , result := range results {
4856+ if result == nil {
4857+ iterationFailCount ++
4858+ }
4859+ }
4860+
4861+ if iterationFailCount > 0 && firstError != nil {
4862+ // Some or all iterations failed — mark the loop step as failed so
4863+ // AnalyzeExecutionResult can detect partial_success at the execution level.
4864+ // Pass the error via the `err` parameter (not `errorMessage`) so that
4865+ // finalizeStep uses err.Error() directly without wrapping it in
4866+ // NewInvalidRequestError which adds an "invalid request: " prefix.
4867+ innerMsg := strings .TrimPrefix (firstError .Error (), "invalid request: " )
4868+ errorMsg := fmt .Sprintf ("%d of %d iterations failed: %s" , iterationFailCount , len (results ), innerMsg )
4869+ loopErr := NewStructuredError (
4870+ avsproto .ErrorCode_INVALID_REQUEST ,
4871+ errorMsg ,
4872+ map [string ]interface {}{
4873+ "failed_iterations" : iterationFailCount ,
4874+ "total_iterations" : len (results ),
4875+ },
4876+ )
4877+ finalizeStep (s , false , loopErr , "" , log .String ())
4878+ return s , nil // return nil error: the loop itself ran to completion
4879+ }
4880+
48534881 finalizeStep (s , success , nil , "" , log .String ())
48544882 return s , nil
48554883}
0 commit comments