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

  1. Use a closed generic dictionary type (Dictionary<string, int>) rather than an open one.
  2. Provide a custom JsonConverter that supplies concrete key/value types.
  3. 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

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


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