{"record":{"id":"3fd9fbeb3ea319d5","repo":"dotnet/efcore","slug":"required-json-property-property-cannot-contain","errorCode":null,"errorMessage":"Required JSON property '{property}' cannot contain null.","messagePattern":"Required JSON property '(.+?)' cannot contain null\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Query/Internal/RelationalJsonUtilities.cs","lineNumber":99,"sourceCode":"                return;\n            }\n\n            writer.WriteStartObject();\n\n            foreach (var property in complexType.GetProperties())\n            {\n                var jsonPropertyName = property.GetJsonPropertyName();\n                Check.DebugAssert(jsonPropertyName is not null);\n                writer.WritePropertyName(jsonPropertyName);\n\n                var jsonValueReaderWriter = property.GetJsonValueReaderWriter() ?? property.GetTypeMapping().JsonValueReaderWriter;\n\n                var propertyValue = property.GetGetter().GetClrValue(objectValue);\n                if (propertyValue is null && jsonValueReaderWriter?.HandlesNullWrites != true)\n                {\n                    if (!property.IsNullable)\n                    {\n                        throw new InvalidOperationException(RelationalStrings.NullValueInRequiredJsonProperty(property.Name));\n                    }\n\n                    writer.WriteNullValue();\n                }\n                else\n                {\n                    Check.DebugAssert(jsonValueReaderWriter is not null, \"Missing JsonValueReaderWriter on JSON property\");\n                    jsonValueReaderWriter.ToJson(writer, propertyValue);\n                }\n            }\n\n            foreach (var complexProperty in complexType.GetComplexProperties())\n            {\n                var jsonPropertyName = complexProperty.GetJsonPropertyName();\n                Check.DebugAssert(jsonPropertyName is not null);\n                writer.WritePropertyName(jsonPropertyName);\n\n                var propertyValue = complexProperty.GetGetter().GetClrValue(objectValue);","sourceCodeStart":81,"sourceCodeEnd":117,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Query/Internal/RelationalJsonUtilities.cs#L81-L117","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before - required (non-nullable) 'Email' inside a JSON-mapped owned type is null\nvar contact = new Contact { Name = \"x\", Details = new ContactDetails { Phone = \"555\", Email = null } };\ncontext.Add(contact);\nawait context.SaveChangesAsync(); // throws: Required JSON property 'Email' cannot contain null.\n\n// after - give the required property a value, or mark it nullable in the model\nvar contact = new Contact { Name = \"x\", Details = new ContactDetails { Phone = \"555\", Email = \"none@example.com\" } };\n// model: modelBuilder.Entity<Contact>().OwnsOne(c => c.Details, d => d.Property(p => p.Email).IsRequired());\n// or make Email nullable if it's truly optional","handlingStrategy":"validation","validationCode":"// Validate required (non-nullable) JSON scalar properties before SaveChanges.\nstatic void ValidateRequiredJsonScalars(IModel model, object entity) {\n    var et = model.FindEntityType(entity.GetType());\n    foreach (var owned in et!.GetNavigations().Where(n => n.TargetEntityType.IsMappedToJson())) {\n        var ownedValue = owned.GetGetter().GetClrValue(entity);\n        if (ownedValue is null) continue;\n        foreach (var p in owned.TargetEntityType.GetProperties()) {\n            if (!p.IsNullable) {\n                var v = p.GetGetter().GetClrValue(ownedValue);\n                if (v is null) throw new ValidationException($\"Required JSON property '{p.Name}' is null.\");\n            }\n        }\n    }\n}","typeGuard":null,"tryCatchPattern":"try { await ctx.SaveChangesAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"Required JSON property\")) {\n    // A non-nullable JSON scalar was null at save time.\n    _logger.LogError(ex, \"Fix null required JSON scalar before saving.\");\n    throw;\n}","preventionTips":["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."],"tags":["ef-core","json","owned-type","complex-type","savechanges","nullable"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}