Retrieving the child items of resource items is not thread-safe


Description

In Sitecore XP 10.2, code changes aimed at application performance optimization have been implemented. However, those changes might result in a race condition that corrupts Sitecore caches. The issue occurs when accessing the child items of a resource item concurrently. The issue is more likely to occur if the number of child items is high. The following message can be found in the logs:

ERROR [Sitecore.Web.HttpModule] Application error.
Exception: System.IndexOutOfRangeException
Message: Index was outside the bounds of the array.
Source: mscorlib
   at System.Collections.Generic.List`1.Add(T item)
   at Sitecore.Data.DataProviders.PrefetchData.AddChildId(ID childId)
   at Sitecore.Data.DataProviders.PrefetchData.AddChildrenForEmptyDefinition(IDList list)
   at Sitecore.Data.DataProviders.Sql.SqlDataProvider.GetChildIDs(ItemDefinition itemDefinition, CallContext context)
   at Sitecore.Data.DataProviders.CompositeDataProvider.<DoGetChildIDs>d__94.MoveNext()
   at Sitecore.Common.EnumerableExtensions.ForEach[T](IEnumerable`1 sequence, Action`1 action)
   at Sitecore.Data.DataProviders.CompositeDataProvider.GetChildIDs(ItemDefinition itemDefinition, CallContext context)
   at Sitecore.Data.DataProviders.DataProvider.GetChildIDs(ItemDefinition item, CallContext context, DataProviderCollection providers)
   at Sitecore.Data.DataSource.GetChildIDs(ID itemID)
   at Sitecore.Nexus.Data.DataCommands.GetChildrenCommand.Execute(Item item)
   ...

or

ERROR Application error.
Exception: System.ArgumentNullException
Message: Value cannot be null.
Parameter name: key
Source: mscorlib
   at System.Collections.Concurrent.ConcurrentDictionary`2.TryGetValue(TKey key, TValue& value)
   at Sitecore.Caching.Generics.Cache`1.InnerBox.DoGetEntry(TKey key, Boolean updateAccessed)
   at Sitecore.Caching.Generics.Cache`1.GetValue(TKey key)
   at Sitecore.Caching.Generics.Cache`1.ContainsKey(TKey key)
   at Sitecore.Data.DataProviders.Sql.SqlDataProvider.EnsureChildrenPrefetched(ID parentId, IDList childIds)
   at Sitecore.Data.DataProviders.Sql.SqlDataProvider.GetChildIDs(ItemDefinition itemDefinition, CallContext context)
   at Sitecore.Data.DataProviders.CompositeDataProvider.<DoGetChildIDs>d__94.MoveNext()
   at Sitecore.Common.EnumerableExtensions.ForEach[T](IEnumerable`1 sequence, Action`1 action)
   at Sitecore.Data.DataProviders.CompositeDataProvider.GetChildIDs(ItemDefinition itemDefinition, CallContext context)
   at Sitecore.Data.DataProviders.DataProvider.GetChildIDs(ItemDefinition item, CallContext context, DataProviderCollection providers)
   at Sitecore.Data.DataSource.GetChildIDs(ID itemID)
   at Sitecore.Nexus.Data.DataCommands.GetChildrenCommand.Execute(Item item)
   ...

Solution

To resolve the issue, consider one of the following options: