dotnet/efcore · error · InvalidOperationException

Required JSON property

Error message

Required JSON property '{property}' cannot contain null.

What it means

Thrown during JSON serialization of an entity mapped to JSON columns when a non-nullable scalar property has a null CLR value and the JsonValueReaderWriter does not handle null writes. This is a data integrity violation: a required (non-nullable) property was set to null at runtime, which EF refuses to silently serialize into JSON.

Solutions

  1. Ensure the property has a non-null value before calling SaveChanges — validate the entity in code.
  2. If the property should allow null, configure it as nullable: IsRequired(false), make the CLR type nullable (int?), or remove [Required].
  3. Add a validator (e.g., in OnSavingChanges or a data annotation validator) that checks JSON-mapped entities for null required properties before save.
  4. If the value comes from external input, reject or default the null at the API boundary.

Example fix

// before
modelBuilder.Entity<Order>().OwnsOne(o => o.Address, a =>
{
    a.ToJson("address");
    a.Property(x => x.ZipCode).IsRequired(); // non-nullable string
});
// Address.ZipCode is null at save time → throws

// after
modelBuilder.Entity<Order>().OwnsOne(o => o.Address, a =>
{
    a.ToJson("address");
    a.Property(x => x.ZipCode).IsRequired(false); // allow null
});
Defensive patterns

Strategy: validation

Validate before calling

// Validate JSON-mapped entities before SaveChanges
foreach (var entry in context.ChangeTracker.Entries())
{
    var entityType = entry.Metadata;
    foreach (var property in entityType.GetProperties())
    {
        if (!property.IsNullable && property.IsJsonMapped())
        {
            var value = entry.CurrentValues[property];
            if (value is null)
                throw new InvalidOperationException(
                    $"Required JSON property {property.Name} on {entityType.DisplayName()} is null before save.");
        }
    }
}

Type guard

static bool IsJsonMappedAndRequired(IProperty property)
    => !property.IsNullable
       && property.DeclaringType.IsMappedToJson();

Try / catch

try
{
    await context.SaveChangesAsync();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Required JSON property") && ex.Message.Contains("cannot contain null"))
{
    logger.LogError(ex, "A required JSON property was null — validate entity data before saving");
    throw;
}

Prevention

When it happens

Trigger: An entity type is mapped to JSON (ToJson mapping) with a non-nullable property (e.g., int, non-nullable string). At save time, the property's CLR value is null — possible via reflection, uninitialized auto-properties, or default value semantics — triggering the throw inside WriteJson when generating the JSON payload.

Common situations: Using [Required] or IsRequired() on a JSON-mapped entity's property but the object instance has that property as null (e.g., partial data from an API payload). Mapping a value type (non-nullable int) but the entity was constructed with Activator.CreateInstance and the getter returns null via a backing field issue. Setting a property to null via reflection or JSON deserialization that bypasses nullability checks.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/3fd9fbeb3ea319d5. Report an issue: GitHub.

Appendix: 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 3a2006ef56)