dotnet/efcore · error · InvalidOperationException
Required JSON property '{property}' cannot contain null.
Error message
Required JSON property '{property}' cannot contain null. What it means
Thrown by RelationalJsonUtilities.SerializeComplexTypeToJson (RelationalJsonUtilities.cs:99) while serializing an entity/complex-type value into its JSON column for SaveChanges. A scalar property declared as non-nullable (IsNullable == false) had a null CLR value at write time and the JSON value reader/writer does not handle null writes. EF refuses to write a null for a required JSON property because that would violate the model's nullability contract inside the JSON document.
Source
Thrown at src/EFCore.Relational/Query/Internal/RelationalJsonUtilities.cs:99
return;
}
writer.WriteStartObject();
foreach (var property in complexType.GetProperties())
{
var jsonPropertyName = property.GetJsonPropertyName();
Check.DebugAssert(jsonPropertyName is not null);
writer.WritePropertyName(jsonPropertyName);
var jsonValueReaderWriter = property.GetJsonValueReaderWriter() ?? property.GetTypeMapping().JsonValueReaderWriter;
var propertyValue = property.GetGetter().GetClrValue(objectValue);
if (propertyValue is null && jsonValueReaderWriter?.HandlesNullWrites != true)
{
if (!property.IsNullable)
{
throw new InvalidOperationException(RelationalStrings.NullValueInRequiredJsonProperty(property.Name));
}
writer.WriteNullValue();
}
else
{
Check.DebugAssert(jsonValueReaderWriter is not null, "Missing JsonValueReaderWriter on JSON property");
jsonValueReaderWriter.ToJson(writer, propertyValue);
}
}
foreach (var complexProperty in complexType.GetComplexProperties())
{
var jsonPropertyName = complexProperty.GetJsonPropertyName();
Check.DebugAssert(jsonPropertyName is not null);
writer.WritePropertyName(jsonPropertyName);
var propertyValue = complexProperty.GetGetter().GetClrValue(objectValue);View on GitHub (pinned to dbf9771522)
Solutions
- Ensure every non-nullable scalar property of the JSON-mapped owned/complex type has a non-null value before SaveChanges.
- If the property is genuinely optional, make it nullable in the model (IsRequired(false) / nullable CLR type) so EF writes a JSON null.
- Initialize required properties in the constructor or with default values.
- Validate the object graph (DataAnnotations / null checks) before calling SaveChanges to surface the bad value earlier.
Example fix
// before - required (non-nullable) 'Email' inside a JSON-mapped owned type is null
var contact = new Contact { Name = "x", Details = new ContactDetails { Phone = "555", Email = null } };
context.Add(contact);
await context.SaveChangesAsync(); // throws: Required JSON property 'Email' cannot contain null.
// after - give the required property a value, or mark it nullable in the model
var contact = new Contact { Name = "x", Details = new ContactDetails { Phone = "555", Email = "none@example.com" } };
// model: modelBuilder.Entity<Contact>().OwnsOne(c => c.Details, d => d.Property(p => p.Email).IsRequired());
// or make Email nullable if it's truly optional Defensive patterns
Strategy: validation
Validate before calling
// Validate required (non-nullable) JSON scalar properties before SaveChanges.
static void ValidateRequiredJsonScalars(IModel model, object entity) {
var et = model.FindEntityType(entity.GetType());
foreach (var owned in et!.GetNavigations().Where(n => n.TargetEntityType.IsMappedToJson())) {
var ownedValue = owned.GetGetter().GetClrValue(entity);
if (ownedValue is null) continue;
foreach (var p in owned.TargetEntityType.GetProperties()) {
if (!p.IsNullable) {
var v = p.GetGetter().GetClrValue(ownedValue);
if (v is null) throw new ValidationException($"Required JSON property '{p.Name}' is null.");
}
}
}
} Try / catch
try { await ctx.SaveChangesAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Required JSON property")) {
// A non-nullable JSON scalar was null at save time.
_logger.LogError(ex, "Fix null required JSON scalar before saving.");
throw;
} Prevention
- Initialize all non-nullable scalar properties of JSON-mapped owned/complex types.
- Add a pre-save validation pass over the object graph.
- Mark genuinely-optional JSON properties nullable (.IsRequired(false)) in the model.
- Unit-test SaveChanges with representative entities to catch nulls early.
When it happens
Trigger: Saving an entity whose JSON-mapped owned/complex type has a non-nullable scalar property set to null. Occurs during SaveChanges/SaveChangesAsync when EF serializes the complex type to the JSON column. Common with owned types mapped ToJson or complex types where a property is required but never assigned.
Common situations: Constructing an owned/complex type without initializing all required (non-nullable) scalar properties (value types left at default, or reference types null); changing a property from nullable to required without updating data; default constructor not setting required fields; recent switch to JSON-mapped owned entities.
Related errors
- JsonCantNavigateToParentEntity
- Required properties '{requiredProperties}' are missing for t
- Required properties '{requiredProperties}' are missing for t
- The optional complex property '{type}.{property}' is mapped
- UnableToBindMemberToEntityProjection
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/3fd9fbeb3ea319d5.
Report an issue: GitHub.