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

I have the following method:

public void CheckInstalledMods()
{
string configText = File.ReadAllText(_dataPath + @"SavedMods/InstalledMods.cfg");

// Destroy any previously created objects, before populating it again.
modsList.Clear();

// If there any mods found, we populate the list with them.
if (configText.Length > 0)
{
installedMods = JsonHelper.FromJson<InstalledMod>(@configText);
modsList.AddRange(installedMods);
modsList.Sort();
}
else // If the file is less than 1, there are no mods found so we add a dummy entry saying the list is empty.
{
// FIX THIS
installedMods = JsonHelper.FromJson<InstalledMod>(@NothingFoundJson);
modsList.AddRange(installedMods);
}
}

When the configText.Length > 0 is true it works exactly as expected. However when that fails the second modsList.AddRange throws the exception in the title. I have carefully checked the ‘NothingFoundJson’ and ensured it has no errors, so I am at a loss to see what the problems is.

Please post the full stack trace. Something is keeping an enumerator around when it shouldn’t be.

InvalidOperationException: Collection was modified; enumeration operation may not execute.
System.Collections.Generic.List1+Enumerator[T].MoveNextRare () (at <a4f9e7f5e7934738b65dad1344f8615e>:0) System.Collections.Generic.List1+Enumerator[T].MoveNext () (at :0)
UI.ModItem.BindEntry (UI.Mod entry) (at Assets/Scripts/UI/ModItem.cs:46)
UI.ModManager.b__38_2 (UnityEngine.UIElements.VisualElement e, System.Int32 i) (at Assets/Scripts/UI/ModManager.cs:371)
UnityEngine.UIElements.CollectionViewController.BindItem (UnityEngine.UIElements.VisualElement element, System.Int32 index) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Controllers/CollectionViewController.cs:111)
UnityEngine.UIElements.CollectionViewController.InvokeBindItem (UnityEngine.UIElements.ReusableCollectionItem reusableItem, System.Int32 index) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Controllers/CollectionViewController.cs:71)
UnityEngine.UIElements.ListViewController.InvokeBindItem (UnityEngine.UIElements.ReusableCollectionItem reusableItem, System.Int32 index) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Controllers/ListViewController.cs:37)
UnityEngine.UIElements.VerticalVirtualizationController1[T].Setup (T recycledItem, System.Int32 newIndex, System.Boolean forceHide) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Virtualization/VerticalVirtualizationController.cs:147) UnityEngine.UIElements.FixedHeightVirtualizationController1[T].Resize (UnityEngine.Vector2 size, System.Int32 layoutPass) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Collections/Virtualization/FixedHeightVirtualizationController.cs:108)
UnityEngine.UIElements.BaseVerticalCollectionView.Resize (UnityEngine.Vector2 size, System.Int32 layoutPass) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Controls/BaseVerticalCollectionView.cs:866)
UnityEngine.UIElements.BaseVerticalCollectionView.OnSizeChanged (UnityEngine.UIElements.GeometryChangedEvent evt) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Controls/BaseVerticalCollectionView.cs:1446)
UnityEngine.UIElements.EventCallbackFunctor`1[TEventType].Invoke (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.PropagationPhase propagationPhase) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/EventCallback.cs:79)
UnityEngine.UIElements.EventCallbackRegistry.InvokeCallbacks (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.PropagationPhase propagationPhase) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/EventCallbackRegistry.cs:353)
UnityEngine.UIElements.CallbackEventHandler.HandleEvent (UnityEngine.UIElements.EventBase evt) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/EventHandler.cs:186)
UnityEngine.UIElements.CallbackEventHandler.HandleEventAtTargetPhase (UnityEngine.UIElements.EventBase evt) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/EventHandler.cs:151)
UnityEngine.UIElements.EventDispatchUtilities.PropagateEvent (UnityEngine.UIElements.EventBase evt) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/IEventDispatchingStrategy.cs:74)
UnityEngine.UIElements.DefaultDispatchingStrategy.DispatchEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Events/DefaultDispatchingStrategy.cs:15)
UnityEngine.UIElements.EventDispatcher.ApplyDispatchingStrategies (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel, System.Boolean imguiEventIsInitiallyUsed) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:381)
UnityEngine.UIElements.EventDispatcher.ProcessEvent (UnityEngine.UIElements.EventBase evt, UnityEngine.UIElements.IPanel panel) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:344)
UnityEngine.UIElements.EventDispatcher.ProcessEventQueue () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:306)
UnityEngine.UIElements.EventDispatcher.OpenGate () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:270)
UnityEngine.UIElements.EventDispatcherGate.Dispose () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/EventDispatcher.cs:75)
UnityEngine.UIElements.UIRLayoutUpdater.Update () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Renderer/UIRLayoutUpdater.cs:57)
UnityEngine.UIElements.VisualTreeUpdater.UpdateVisualTreePhase (UnityEngine.UIElements.VisualTreeUpdatePhase phase) (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/VisualTreeUpdater.cs:155)
UnityEngine.UIElements.Panel.ValidateLayout () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Panel.cs:943)
UnityEngine.UIElements.BaseVisualElementPanel.Update () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/Panel.cs:577)
UnityEngine.UIElements.RuntimePanel.Update () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/GameObjects/RuntimePanel.cs:47)
UnityEngine.UIElements.UIElementsRuntimeUtility.UpdateRuntimePanels () (at /home/bokken/buildslave/unity/build/ModuleOverrides/com.unity.ui/Core/UIElementsRuntimeUtility.cs:209)
UnityEngine.UIElements.UIElementsRuntimeUtilityNative.UpdateRuntimePanels () (at /home/bokken/buildslave/unity/build/Modules/UIElementsNative/UIElementsUtility.bindings.cs:26)

Looks like the problem is somewhere in one of these methods:

Many thanks.

That allowed me to narrow down the problem. I had assumed the collection in question was modsList. This was only indirectly true as it is the source list for a ListView element. The actual problem was that I was modifying the hierarchy in a ListView element when the data binding was being done. So the collection in question was the ListView row, I think.

Anyhow, I have re-architected the binding so that the element is not instantiated until after the changes are made. All seems good now.

Wait data binding works at runtime now? WHAAAT? When did that happen?

Ummm, may be I chose the wrong phrase there. The ‘binding’ of the List is done normally with the ListView(source, itemHeight, makeItem, bindItem). But the actual data is bound to the row at runtime by the bindItem callback. In my case, that is a method of the makeItem class so that I can set somw attribute depending on the data.