stride3d/stride · error · InvalidOperationException

Unable to remove this value at the given index because it…

Error message

Unable to remove this value at the given index because it wasn't found in the ObservableSet.

What it means

ObservableSet.RemoveItem must find the item at the given index in its internal HashSet. If hashSet.Remove fails, the list content and hash set are out of sync — a broken internal invariant the class never expects, so it throws a diagnostic InvalidOperationException.

Solutions

  1. Make items stored in an ObservableSet immutable, or at least keep GetHashCode/Equals stable while contained
  2. Ensure GetHashCode/Equals/comparer are consistent — do not mutate fields they depend on
  3. Avoid manipulating internal list/hashSet state outside the class API
  4. If you see it with correct usage, report as a library bug (the code comments it 'shouldn't happen')

Example fix

// before
class Item { public int Id; } // mutable Id used in GetHashCode
item.Id = 5; // hash changes -> unremovable
// after
class Item { public int Id { get; } } // immutable key, stable hash
Defensive patterns

Strategy: validation

Validate before calling

// Ensure items' GetHashCode/Equals are stable: use immutable key fields

Try / catch

try { set.Remove(item); } catch (InvalidOperationException ex) { logger.Error(ex, "hashset/list desync in ObservableSet"); }

Prevention

When it happens

Trigger: External code tampering with the underlying list/hashset; a comparer or GetHashCode implementation whose hash changes after insertion, making stored items unfindable; bugs in overridden equality that make removal fail.

Common situations: Mutable items whose GetHashCode/Equals changes while stored in the set; custom equality comparers inconsistent with the stored state; concurrent modification corrupting internal state.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/c47b553c3e7abc10. Report an issue: GitHub.

Appendix: source

Thrown at sources/presentation/Stride.Core.Presentation/Collections/ObservableSet.cs:109

        {
            var oldItem = base[index];
            hashSet.Remove(oldItem);
            if (!hashSet.Add(item))
            {
                // restore removed item
                hashSet.Add(oldItem);
                throw new InvalidOperationException("Unable to set this value at the given index because this value is already contained in this ObservableSet.");
            }
            base.SetItem(index, item);
        }

        protected override void RemoveItem(int index)
        {
            var item = base[index];
            if (!hashSet.Remove(item))
            {
                // safety check: shouldn't happen. If it does, we have a failed logic somewhere.
                throw new InvalidOperationException("Unable to remove this value at the given index because it wasn't found in the ObservableSet.");
            }
            base.RemoveItem(index);
        }

        /// <inheritdoc/>
        [CollectionAccess(CollectionAccessType.None)]
        public override string ToString()
        {
            return $"{{ObservableSet}} Count = {Count}";
        }

#if SUPPORT_RANGE_ACTION
        /// <summary>
        /// Helper to raise a PropertyChanged event for the Count property
        /// </summary>
        private void OnCountPropertyChanged() => OnPropertyChanged(new PropertyChangedEventArgs("Count"));

        /// <summary>

View on GitHub (pinned to 96fad776d2)