{"record":{"id":"83bb852166e5fdbf","repo":"JamesNK/Newtonsoft.Json","slug":"wrapped-icollection-t-does-not-support-removeat","errorCode":null,"errorMessage":"Wrapped ICollection<T> does not support RemoveAt.","messagePattern":"Wrapped ICollection<T> does not support RemoveAt\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs","lineNumber":216,"sourceCode":"        {\n            if (_genericCollection != null)\n            {\n                throw new InvalidOperationException(\"Wrapped ICollection<T> does not support IndexOf.\");\n            }\n\n            if (IsCompatibleObject(value))\n            {\n                return _list!.IndexOf((T)value!);\n            }\n\n            return -1;\n        }\n\n        void IList.RemoveAt(int index)\n        {\n            if (_genericCollection != null)\n            {\n                throw new InvalidOperationException(\"Wrapped ICollection<T> does not support RemoveAt.\");\n            }\n\n            _list!.RemoveAt(index);\n        }\n\n        void IList.Insert(int index, object? value)\n        {\n            if (_genericCollection != null)\n            {\n                throw new InvalidOperationException(\"Wrapped ICollection<T> does not support Insert.\");\n            }\n\n            VerifyValueType(value);\n            _list!.Insert(index, (T)value!);\n        }\n\n        bool IList.IsFixedSize\n        {","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/JamesNK/Newtonsoft.Json/blob/4f73e74372445108d2c1bda37b36e6f5e43402e0/Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs#L198-L234","documentation":"Thrown by CollectionWrapper<T>.IList.RemoveAt when the underlying collection is an ICollection<T> and therefore has no RemoveAt semantics. The wrapper can only honor RemoveAt when the source is an IList; otherwise it throws InvalidOperationException.","triggerScenarios":"Json.NET (or user code via a CollectionWrapper) attempts positional removal on a HashSet<T>, Dictionary.ValueCollection, or other ICollection<T>-but-not-IList collection during (de)serialization or a custom converter.","commonSituations":"Custom converters/contracts that expose a set-like collection but the pipeline expects list semantics; mutating a deserialized set via index operations; binding redirects/version changes that alter the wrapper's collection detection.","solutions":["Use an IList<T>-backed collection (List<T>) when positional remove is required.","Avoid RemoveAt-style operations in custom converters operating on ICollection<T>.","Materialize into a List<T> before performing index mutations.","Adjust the contract so Json.NET chooses an IList-capable wrapper."],"exampleFix":"// before: RemoveAt on a HashSet wrapper\nvar set = new HashSet<int>{1,2,3};\nvar wrapper = new CollectionWrapper<int>(set);\nwrapper.RemoveAt(0); // throws\n// after: back with a List\nvar list = new List<int>{1,2,3};\nvar wrapper = new CollectionWrapper<int>(list);\nwrapper.RemoveAt(0);","handlingStrategy":"type-guard","validationCode":"if (!(collection is IList)) throw new NotSupportedException(\"RemoveAt requires an IList\");","typeGuard":"static bool SupportsRemoveAt<T>(ICollection<T> c) => c is IList;","tryCatchPattern":"try { ((IList)wrapper).RemoveAt(i); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"does not support RemoveAt\")) {\n    logger.Error(ex, \"underlying collection is not positional; use a List<T>.\"); throw;\n}","preventionTips":["Back wrappers with List<T> when positional remove is needed.","Use Remove(item) semantics on set-like collections instead of RemoveAt.","Audit custom converters for positional mutation of ICollection<T>.","Choose IList-capable target types in deserialization."],"tags":["collection-wrapper","icollection","notsupported","index-access"],"analyzedSha":"4f73e74372445108d2c1bda37b36e6f5e43402e0","analyzedAt":"2026-08-07T06:10:08.596Z","schemaVersion":2},"datasetVersion":"2026-08-07T07:17:06.508Z"}