JamesNK/Newtonsoft.Json · error · InvalidOperationException
Wrapped ICollection<T> does not support RemoveAt.
Error message
Wrapped ICollection<T> does not support RemoveAt.
What it means
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.
Source
Thrown at Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs:216
{
if (_genericCollection != null)
{
throw new InvalidOperationException("Wrapped ICollection<T> does not support IndexOf.");
}
if (IsCompatibleObject(value))
{
return _list!.IndexOf((T)value!);
}
return -1;
}
void IList.RemoveAt(int index)
{
if (_genericCollection != null)
{
throw new InvalidOperationException("Wrapped ICollection<T> does not support RemoveAt.");
}
_list!.RemoveAt(index);
}
void IList.Insert(int index, object? value)
{
if (_genericCollection != null)
{
throw new InvalidOperationException("Wrapped ICollection<T> does not support Insert.");
}
VerifyValueType(value);
_list!.Insert(index, (T)value!);
}
bool IList.IsFixedSize
{View on GitHub (pinned to 4f73e74372)
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.
Example fix
// before: RemoveAt on a HashSet wrapper
var set = new HashSet<int>{1,2,3};
var wrapper = new CollectionWrapper<int>(set);
wrapper.RemoveAt(0); // throws
// after: back with a List
var list = new List<int>{1,2,3};
var wrapper = new CollectionWrapper<int>(list);
wrapper.RemoveAt(0); Defensive patterns
Strategy: type-guard
Validate before calling
if (!(collection is IList)) throw new NotSupportedException("RemoveAt requires an IList"); Type guard
static bool SupportsRemoveAt<T>(ICollection<T> c) => c is IList;
Try / catch
try { ((IList)wrapper).RemoveAt(i); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not support RemoveAt")) {
logger.Error(ex, "underlying collection is not positional; use a List<T>."); throw;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Wrapped ICollection<T> does not support IndexOf.
- Wrapped ICollection<T> does not support Insert.
- Newtonsoft.Json support for dynamic is not compatible with t
- Newtonsoft.Json support for dynamic is not compatible with t
- Newtonsoft.Json serialization is not compatible with trimmin
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/83bb852166e5fdbf.
Report an issue: GitHub.