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
- Initialize the dictionary at declaration: 'get;' backed by '= new Dictionary<string, JToken>()'.
- Give the property a setter so Json.NET can create and assign the dictionary.
- 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
- Initialize extension-data collections at declaration: '= new Dictionary<string, JToken>()'.
- Give the extension-data property a setter, or set it in a constructor.
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
- No object created.
- Unexpected BsonType value: {0}
- Unable to read beyond the end of the stream.
- Expected Bytes but got {0}.
- Expected JSON property '{0}'.
AI-assisted analysis of JamesNK/Newtonsoft.Json@4f73e74372 (2026-08-07).
Data as JSON: /api/errors/4908460cf29432c3.
Report an issue: GitHub.