JamesNK/Newtonsoft.Json · error · JsonSerializationException

Cannot set value onto extension data member '{0}'. The exten

Error message

Cannot set value onto extension data member '{0}'. The extension data collection is null and it cannot be set.

What it means

When reading extra JSON properties into an extension-data member, Json.NET reads the member's dictionary at runtime; if it is null and the member cannot be assigned (no setter / not settable, so setExtensionDataDictionary is null), the ExtensionDataSetter throws a JsonSerializationException (line 546). The library cannot create a dictionary and assign it back, so capture fails.

Source

Thrown at Src/Newtonsoft.Json/Serialization/DefaultContractResolver.cs:546

                Func<object> createExtensionDataDictionary = JsonTypeReflector.ReflectionDelegateFactory.CreateDefaultConstructor<object>(createdType);
                MethodInfo? setMethod = t.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, valueType, new[] { keyType }, null)?.GetSetMethod();
                if (setMethod == null)
                {
                    // Item is explicitly implemented and non-public
                    // get from dictionary interface
                    setMethod = dictionaryType!.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance, null, valueType, new[] { keyType }, null)?.GetSetMethod();
                }

                MethodCall<object, object?> setExtensionDataDictionaryValue = JsonTypeReflector.ReflectionDelegateFactory.CreateMethodCall<object>(setMethod!);

                ExtensionDataSetter extensionDataSetter = (o, key, value) =>
                {
                    object? dictionary = getExtensionDataDictionary(o);
                    if (dictionary == null)
                    {
                        if (setExtensionDataDictionary == null)
                        {
                            throw new JsonSerializationException("Cannot set value onto extension data member '{0}'. The extension data collection is null and it cannot be set.".FormatWith(CultureInfo.InvariantCulture, member.Name));
                        }

                        dictionary = createExtensionDataDictionary();
                        setExtensionDataDictionary(o, dictionary);
                    }

                    setExtensionDataDictionaryValue(dictionary, key, value);
                };

                contract.ExtensionDataSetter = extensionDataSetter;
            }

            if (extensionDataAttribute.WriteData)
            {
                Type enumerableWrapper = typeof(EnumerableDictionaryWrapper<,>).MakeGenericType(keyType, valueType);
                ConstructorInfo constructors = enumerableWrapper.GetConstructors().First();
                ObjectConstructor<object> createEnumerableWrapper = JsonTypeReflector.ReflectionDelegateFactory.CreateParameterizedConstructor(constructors);

View on GitHub (pinned to 4f73e74372)

Solutions

  1. Initialize the dictionary at declaration: 'get;' backed by '= new Dictionary<string, JToken>()'.
  2. Give the property a setter so Json.NET can create and assign the dictionary.
  3. Initialize the collection in the type's constructor before deserialization.

Example fix

// before
[JsonExtensionData]
public IDictionary<string, JToken> Extra { get; } // null at runtime -> throws

// after
[JsonExtensionData]
public IDictionary<string, JToken> Extra { get; set; } = new Dictionary<string, JToken>();
Defensive patterns

Strategy: validation

Validate before calling

foreach (var p in typeof(T).GetProperties().Where(p => p.IsDefined(typeof(JsonExtensionDataAttribute), false)))
{
    var attr = (JsonExtensionDataAttribute)Attribute.GetCustomAttribute(p, typeof(JsonExtensionDataAttribute));
    if (attr.ReadData && p.GetSetMethod(true) == null)
    {
        // property has no setter -> must be initialized in a constructor or initializer
        var ctorInit = typeof(T).GetConstructors().Any(c => /* check field/prop assignment */ false);
        if (!ctorInit)
            throw new InvalidOperationException($"{p.Name} is read-only; initialize it or add a setter.");
    }
}

Type guard

static bool ExtensionDataIsSafeForRead(MemberInfo m)
{
    var attr = (JsonExtensionDataAttribute)Attribute.GetCustomAttribute(m, typeof(JsonExtensionDataAttribute))!;
    if (attr == null || !attr.ReadData) return true;
    var prop = m as PropertyInfo;
    return prop == null || prop.GetSetMethod(true) != null || /* initialized elsewhere */ false;
}

Try / catch

try { JsonConvert.DeserializeObject<T>(json); }
catch (JsonSerializationException ex) when (ex.Message.Contains("extension data collection is null"))
{
    // initialize the dictionary at declaration or add a setter
}

Prevention

When it happens

Trigger: [JsonExtensionData] (with ReadData = true, the default) on a get-only property whose backing dictionary is never initialized, then deserializing JSON that contains properties not mapped to members.

Common situations: Auto-property with only a getter and no initializer, or a readonly field left null, used to collect overflow properties during deserialization.

Related errors


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