{"record":{"id":"ed8e622c8fd90983","repo":"dotnet/efcore","slug":"complex-property-complexproperty-is-mapped-to","errorCode":null,"errorMessage":"Complex property '{complexProperty}' is mapped to JSON but its containing type '{containingType}' is not. Map the root complex type to JSON. See https://github.com/dotnet/efcore/issues/36558.","messagePattern":"Complex property '(.+?)' is mapped to JSON but its containing type '(.+?)' is not\\. Map the root complex type to JSON\\. See https://github\\.com/dotnet/efcore/issues/36558\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs","lineNumber":307,"sourceCode":"                        columnName,\n                        complexProperty.GetJsonPropertyName()));\n            }\n\n            if (!complexProperty.DeclaringType.IsMappedToJson())\n            {\n                throw new InvalidOperationException(\n                    RelationalStrings.ComplexPropertyJsonPropertyNameWithoutJsonMapping(\n                        $\"{complexProperty.DeclaringType.DisplayName()}.{complexProperty.Name}\"));\n            }\n        }\n\n        if (complexProperty.ComplexType.IsMappedToJson())\n        {\n            if (!complexProperty.DeclaringType.IsMappedToJson()\n                && complexProperty.DeclaringType is IComplexType)\n            {\n                // Issue #36558\n                throw new InvalidOperationException(\n                    RelationalStrings.NestedComplexPropertyJsonWithTableSharing(\n                        $\"{complexProperty.DeclaringType.DisplayName()}.{complexProperty.Name}\",\n                        complexProperty.DeclaringType.DisplayName()));\n            }\n\n            ValidateJsonProperties(complexProperty.ComplexType);\n        }\n    }\n\n    /// <summary>\n    ///     Validates the SQL query mapping for an entity type.\n    /// </summary>\n    /// <param name=\"entityType\">The entity type to validate.</param>\n    /// <param name=\"logger\">The logger to use.</param>\n    protected virtual void ValidateSqlQuery(\n        IEntityType entityType,\n        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)\n    {","sourceCodeStart":289,"sourceCodeEnd":325,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs#L289-L325","documentation":"ValidatePropertyMapping throws NestedComplexPropertyJsonWithTableSharing when a complex property is mapped to JSON (ComplexType.IsMappedToJson() is true) but its declaring type is itself a ComplexType that is NOT mapped to JSON. A JSON complex nested inside a non-JSON complex is ambiguous (the outer one is flattened to columns). Tracked as Issue #36558; the message points developers to map the root complex type to JSON.","triggerScenarios":"A nested complex property where the inner complex is configured with ToJson but the outer (containing) complex is not — i.e. outer flattens to columns while inner wants JSON. The check is `complexProperty.ComplexType.IsMappedToJson() && !DeclaringType.IsMappedToJson() && DeclaringType is IComplexType`.","commonSituations":"Adding ToJson only on the inner complex of a nested value-object graph; refactoring where the outer ToJson was removed but the inner kept; scaffolding that inconsistently applies JSON mapping across nesting levels.","solutions":["Map the outermost (root) complex property to JSON with ToJson(), so the entire nested graph is JSON.","Alternatively, remove ToJson from the inner complex property so the whole graph is flattened to columns.","Ensure JSON mapping is consistent up the complex-property chain — either all JSON from the root or none."],"exampleFix":"// before — outer Address flattened, inner Geo mapped to JSON\nmodelBuilder.Entity<Customer>()\n    .OwnsOne(c => c.Address, a =>\n    {\n        a.OwnsOne(a2 => a2.Geo, g => g.ToJson(\"geo\")); // throws\n    });\n\n// after — map the root complex to JSON\nmodelBuilder.Entity<Customer>()\n    .OwnsOne(c => c.Address, a =>\n    {\n        a.ToJson(\"address\");\n        a.OwnsOne(a2 => a2.Geo, g => { /* inherits JSON mapping */ });\n    });","handlingStrategy":"validation","validationCode":"if (complexProperty.ComplexType.IsMappedToJson()\n    && !complexProperty.DeclaringType.IsMappedToJson()\n    && complexProperty.DeclaringType is IComplexType)\n    throw new InvalidOperationException(\"Inner complex is JSON but outer complex is not; map the root to JSON.\");","typeGuard":"static bool HasInconsistentNestedJsonMapping(IComplexProperty cp)\n    => cp.ComplexType.IsMappedToJson()\n       && !cp.DeclaringType.IsMappedToJson()\n       && cp.DeclaringType is IComplexType;","tryCatchPattern":null,"preventionTips":["Apply ToJson() at the root complex property when nested complexes use JSON.","Keep JSON mapping consistent up the complex-property chain — all or none.","Validate nested complex graphs at model finalization in a unit test."],"tags":["complex-type","nested-complex","json-mapping","model-validation"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}