JamesNK/Newtonsoft.Json · error · ArgumentException

The value '{0}' is not of type '{1}' and cannot be used in t

Error message

The value '{0}' is not of type '{1}' and cannot be used in this generic collection.

What it means

CollectionWrapper<T> is strongly typed to element type T. The non-generic IList path (Add, Insert, indexer set) calls VerifyValueType (CollectionWrapper.cs:300-306), which uses IsCompatibleObject to check the value is assignable to T. If the runtime type isn't compatible (e.g. adding an int into a List<string>), it throws ArgumentException with the value and the expected type T.

Source

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

        object ICollection.SyncRoot
        {
            get
            {
                if (_syncRoot == null)
                {
                    Interlocked.CompareExchange(ref _syncRoot, new object(), null);
                }

                return _syncRoot;
            }
        }

        private static void VerifyValueType(object? value)
        {
            if (!IsCompatibleObject(value))
            {
                throw new ArgumentException("The value '{0}' is not of type '{1}' and cannot be used in this generic collection.".FormatWith(CultureInfo.InvariantCulture, value, typeof(T)), nameof(value));
            }
        }

        private static bool IsCompatibleObject(object? value)
        {
            if (!(value is T) && (value != null || (typeof(T).IsValueType() && !ReflectionUtils.IsNullableType(typeof(T)))))
            {
                return false;
            }

            return true;
        }

        public object UnderlyingCollection => (object)_genericCollection! ?? _list!;
    }
}

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Align the JSON array element type with the collection's element type T (e.g. send numbers for List<int>).
  2. Register a JsonConverter that converts each element to T before it reaches the collection.
  3. Widen the element type (use List<object> or a base type) if the array is heterogeneous.
  4. Enable TypeNameHandling and emit $type for polymorphic arrays.
  5. Validate the JSON payload against the expected schema before deserialization.

Example fix

// before
public List<int> Ids { get; set; }  // JSON: ["42","43"] -> strings into int list
// after
public List<int> Ids { get; set; }  // JSON: [42,43]
//   OR add a converter that parses numeric strings to int
Defensive patterns

Strategy: type-guard

Validate before calling

// Validate each element matches T before inserting via the non-generic IList path.
static void SafeAdd<T>(System.Collections.Generic.ICollection<T> c, object value) {
    if (value is T t || (value == null && default(T) == null)) c.Add(t);
    else throw new InvalidOperationException($"{value?.GetType()} is not compatible with {typeof(T)}.");
}

Type guard

static bool IsCompatible<T>(object? value) => value is T || (value == null && (!typeof(T).IsValueType || System.Nullable.GetUnderlyingType(typeof(T)) != null));

Try / catch

try { list.Add(value); } catch (ArgumentException ex) when (ex.Message.Contains("is not of type")) { /* log schema mismatch; coerce or skip */ }

Prevention

When it happens

Trigger: Deserializing a JSON array whose element CLR type (after conversion) doesn't match the target collection's element type T, with the value flowing through the IList.Add/Insert/indexer-set path. Also triggered by a custom converter returning the wrong element type.

Common situations: Mixed-type JSON arrays deserialized into strongly-typed List<T>; polymorphic payloads without TypeNameHandling; custom JsonConverter returning a type that isn't T; schema drift where a field changed type.

Related errors


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