JamesNK/Newtonsoft.Json · error · Exception
Type {0} is not a dictionary.
Error message
Type {0} is not a dictionary. What it means
Thrown by ReflectionUtils.GetDictionaryKeyValueTypes when a type implements IDictionary<,> but the resolved implementing generic type is a generic type definition (open / unbound). The key/value types could not be resolved to concrete types, analogous to error 269 for collections.
Source
Thrown at Src/Newtonsoft.Json/Utilities/ReflectionUtils.cs:447
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)
{
ValidationUtils.ArgumentNotNull(dictionaryType, nameof(dictionaryType));
if (ImplementsGenericDefinition(dictionaryType, typeof(IDictionary<,>), out Type? genericDictionaryType))
{
if (genericDictionaryType!.IsGenericTypeDefinition())
{
throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
}
Type[] dictionaryGenericArguments = genericDictionaryType!.GetGenericArguments();
keyType = dictionaryGenericArguments[0];
valueType = dictionaryGenericArguments[1];
return;
}
if (typeof(IDictionary).IsAssignableFrom(dictionaryType))
{
keyType = null;
valueType = null;
return;
}
throw new Exception("Type {0} is not a dictionary.".FormatWith(CultureInfo.InvariantCulture, dictionaryType));
}
View on GitHub (pinned to 4f73e74372)
Solutions
- Use a closed generic dictionary type (Dictionary<string, int>) rather than an open one.
- Provide a custom JsonConverter that supplies concrete key/value types.
- Ensure any type-name-resolved dictionary type is closed.
Example fix
// before Type t = typeof(Dictionary<,>); ReflectionUtils.GetDictionaryKeyValueTypes(t, out var k, out var v); // after Type t = typeof(Dictionary<string, int>); ReflectionUtils.GetDictionaryKeyValueTypes(t, out var k, out var v);
Defensive patterns
Strategy: validation
Validate before calling
if (t.IsGenericType && t.ContainsGenericParameters)
throw new ArgumentException("Pass a closed generic dictionary, not an open definition."); Type guard
static bool IsClosedGenericDictionary(Type t) => t.IsGenericType && !t.ContainsGenericParameters && typeof(IDictionary).IsAssignableFrom(t);
Prevention
- Never pass open generic dictionary definitions; use closed instances.
- Guard with ContainsGenericParameters before dictionary resolution.
- Provide a custom converter for open-generic base dictionary types.
When it happens
Trigger: A type whose IDictionary<,> implementation is still open — abstract generic dictionary bases, or dynamically constructed open generic types reaching this path.
Common situations: Custom generic dictionary base classes used directly, open generic types leaking into dictionary resolution, or TypeNameHandling resolving to an unbound generic dictionary.
Related errors
- Type {0} is not a collection.
- '{0}' is not a generic interface definition.
- '{0}' is not a generic class definition.
- type
- Unexpected type code '{0}' for type '{1}'.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/c5838294c0893be7.
Report an issue: GitHub.