{"record":{"id":"c47b553c3e7abc10","repo":"stride3d/stride","slug":"unable-to-remove-this-value-at-the-given-index-because-it","errorCode":null,"errorMessage":"Unable to remove this value at the given index because it wasn't found in the ObservableSet.","messagePattern":"Unable to remove this value at the given index because it wasn't found in the ObservableSet\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/presentation/Stride.Core.Presentation/Collections/ObservableSet.cs","lineNumber":109,"sourceCode":"        {\n            var oldItem = base[index];\n            hashSet.Remove(oldItem);\n            if (!hashSet.Add(item))\n            {\n                // restore removed item\n                hashSet.Add(oldItem);\n                throw new InvalidOperationException(\"Unable to set this value at the given index because this value is already contained in this ObservableSet.\");\n            }\n            base.SetItem(index, item);\n        }\n\n        protected override void RemoveItem(int index)\n        {\n            var item = base[index];\n            if (!hashSet.Remove(item))\n            {\n                // safety check: shouldn't happen. If it does, we have a failed logic somewhere.\n                throw new InvalidOperationException(\"Unable to remove this value at the given index because it wasn't found in the ObservableSet.\");\n            }\n            base.RemoveItem(index);\n        }\n\n        /// <inheritdoc/>\n        [CollectionAccess(CollectionAccessType.None)]\n        public override string ToString()\n        {\n            return $\"{{ObservableSet}} Count = {Count}\";\n        }\n\n#if SUPPORT_RANGE_ACTION\n        /// <summary>\n        /// Helper to raise a PropertyChanged event for the Count property\n        /// </summary>\n        private void OnCountPropertyChanged() => OnPropertyChanged(new PropertyChangedEventArgs(\"Count\"));\n\n        /// <summary>","sourceCodeStart":91,"sourceCodeEnd":127,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/presentation/Stride.Core.Presentation/Collections/ObservableSet.cs#L91-L127","documentation":"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.","triggerScenarios":"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.","commonSituations":"Mutable items whose GetHashCode/Equals changes while stored in the set; custom equality comparers inconsistent with the stored state; concurrent modification corrupting internal state.","solutions":["Make items stored in an ObservableSet immutable, or at least keep GetHashCode/Equals stable while contained","Ensure GetHashCode/Equals/comparer are consistent — do not mutate fields they depend on","Avoid manipulating internal list/hashSet state outside the class API","If you see it with correct usage, report as a library bug (the code comments it 'shouldn't happen')"],"exampleFix":"// before\nclass Item { public int Id; } // mutable Id used in GetHashCode\nitem.Id = 5; // hash changes -> unremovable\n// after\nclass Item { public int Id { get; } } // immutable key, stable hash","handlingStrategy":"validation","validationCode":"// Ensure items' GetHashCode/Equals are stable: use immutable key fields","typeGuard":null,"tryCatchPattern":"try { set.Remove(item); } catch (InvalidOperationException ex) { logger.Error(ex, \"hashset/list desync in ObservableSet\"); }","preventionTips":["Use immutable items or immutable hash keys in sets","Never change fields used by GetHashCode/Equals while item is in the set","Keep equality comparer consistent across the item's lifetime"],"tags":["collections","set","hashcode"],"backgroundTag":"internal-invariant-violation","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}