Running GetEnvironmentCacheBlock may cause the "Collection was modified" message in log files of a Commerce Engine instance


Description

The following exception might appear in the log files of a Commerce Engine instance (Authoring, Shops, and so on) when Sitecore.Commerce.Core.GetEnvironmentCacheBlock is executed in parallel threads:

System.InvalidOperationException: Collection was modified; enumeration operation may not execute

The cause of the issue is related to the fact that a collection cannot be modified while IEnumerator is used to iterate it. Such modification leads to throwing the previously mentioned exception with the following stack trace:

ERROR Pipeline completed with error
System.Exception: Error processing block: Core.block.GetEnvironmentCache ---> System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
   at System.ThrowHelper.ThrowInvalidOperationException(ExceptionResource resource)
   at System.Collections.Generic.List`1.Enumerator.MoveNextRare()
   at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable`1 source, Func`2 predicate)
   at Sitecore.Commerce.Core.GetEnvironmentCacheBlock.Run(EnvironmentCacheArgument arg, CommercePipelineExecutionContext context)
   --- End of inner exception stack trace ---
   at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
   at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
   at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
   at Sitecore.Framework.Pipelines.ReflectionPipelineBlockRunner.<InvokeBlock>d__2.MoveNext()
   --- End of inner exception stack trace ---
   at Sitecore.Framework.Pipelines.ReflectionPipelineBlockRunner.<InvokeBlock>d__2.MoveNext()
   --- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Sitecore.Framework.Pipelines.BasePipelineBlockRunner.<Run>d__3`1.MoveNext()

Solution

To resolve the issue, consider the following options for the solution: