JamesNK/Newtonsoft.Json · error · Exception
Type {0} is not a collection.
Error message
Type {0} is not a collection. What it means
Thrown by ReflectionUtils.GetCollectionItemType when a type implements IEnumerable<> but the resolved implementing generic type is itself a generic type definition (still open / unbound). This is an edge case where the element type could not be resolved to a concrete type. The collection lookup succeeded structurally but the type argument remains an open T.
Source
Thrown at Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs:422
/// Gets the type of the typed collection's items.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>The type of the typed collection's items.</returns>
public static Type? GetCollectionItemType(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
Type type)
{
ValidationUtils.ArgumentNotNull(type, nameof(type));
if (type.IsArray)
{
return type.GetElementType();
}
if (ImplementsGenericDefinition(type, typeof(IEnumerable<>), out Type? genericListType))
{
if (genericListType!.IsGenericTypeDefinition())
{
throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
}
return genericListType!.GetGenericArguments()[0];
}
if (typeof(IEnumerable).IsAssignableFrom(type))
{
return null;
}
throw new Exception("Type {0} is not a collection.".FormatWith(CultureInfo.InvariantCulture, type));
}
public static void GetDictionaryKeyValueTypes(
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)]
Type dictionaryType,
out Type? keyType,
out Type? valueType)
{View on GitHub (pinned to 4f73e74372)
Solutions
- Serialize/deserialize a closed generic instance (List<int>) rather than the open generic type definition.
- Provide a custom JsonConverter that knows the concrete element type.
- Ensure any TypeNameHandling-supplied type name resolves to a closed generic.
Example fix
// before Type t = typeof(List<>); // open generic var itemType = ReflectionUtils.GetCollectionItemType(t); // after Type t = typeof(List<int>); // closed generic var itemType = ReflectionUtils.GetCollectionItemType(t);
Defensive patterns
Strategy: validation
Validate before calling
if (t.IsGenericType && t.ContainsGenericParameters)
throw new ArgumentException("Pass a closed generic collection, not an open definition."); Type guard
static bool IsClosedGenericCollection(Type t) => t.IsGenericType && !t.ContainsGenericParameters && typeof(IEnumerable).IsAssignableFrom(t);
Prevention
- Never pass open generic type definitions to collection-handling code; use closed instances.
- Guard types with ContainsGenericParameters before collection resolution.
- Provide a custom converter for open-generic base collection types.
When it happens
Trigger: A type whose IEnumerable<> implementation is open (unresolved T) — abstract generic collection bases, or dynamically constructed open generic types reaching GetCollectionItemType. Often seen with reflection-emitted open generic types or misused TypeNameHandling producing open generics.
Common situations: Custom generic base classes used as collection types, open generic types leaking into the collection item-type resolution path, or deserializing with TypeNameHandling that resolves to an unbound generic.
Related errors
- Type {0} is not a dictionary.
- '{0}' is not a generic interface definition.
- '{0}' is not a generic class definition.
- Cannot add or remove items from {0}.
- {0} cannot have multiple values.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/37a04e3853720c81.
Report an issue: GitHub.