JamesNK/Newtonsoft.Json · error · InvalidOperationException

Wrapped ICollection<T> does not support Insert.

Error message

Wrapped ICollection<T> does not support Insert.

What it means

Thrown by CollectionWrapper<T>.IList.Insert when the underlying collection is an ICollection<T> that is not an IList, because insertion at a position requires index semantics that ICollection<T> does not provide.

Source

Thrown at Src/Newtonsoft.Json/Utilities/CollectionWrapper.cs:226

            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
        {
            get
            {
                if (_genericCollection != null)
                {
                    // ICollection<T> only has IsReadOnly
                    return _genericCollection.IsReadOnly;
                }
                else
                {
                    return _list!.IsFixedSize;

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Back the wrapper with an IList<T> (List<T>) when positional insert is needed.
  2. Use Add semantics (no position) instead of Insert for set-like collections.
  3. Modify custom converters/contracts so they do not call Insert on ICollection<T>-only collections.
  4. Choose target collection types that implement IList<T> for ordered insertion use cases.

Example fix

// before: Insert on HashSet wrapper
var set = new HashSet<int>();
var wrapper = new CollectionWrapper<int>(set);
wrapper.Insert(0, 1); // throws
// after: List-backed wrapper supports Insert
var list = new List<int>();
var wrapper = new CollectionWrapper<int>(list);
wrapper.Insert(0, 1);
Defensive patterns

Strategy: type-guard

Validate before calling

if (!(collection is IList)) throw new NotSupportedException("Insert requires an IList");

Type guard

static bool SupportsInsert<T>(ICollection<T> c) => c is IList;

Try / catch

try { ((IList)wrapper).Insert(0, item); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not support Insert")) {
    logger.Error(ex, "underlying collection is not positional; use a List<T>."); throw;
}

Prevention

When it happens

Trigger: A CollectionWrapper wrapping an ICollection<T> (e.g. HashSet<T>) is asked to Insert(index, value). Reached during deserialization or via a custom converter/contract that drives positional insertion against a non-indexed collection.

Common situations: Deserializing JSON into a HashSet/set collection while a converter or the contract requests Insert; using CollectionWrapper directly against non-list collections; misconfigured collection contracts after refactoring.

Related errors


AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07). Data as JSON: /api/errors/3554730b8148c66c. Report an issue: GitHub.