{"record":{"id":"3495b0ed40208fac","repo":"dotnet/efcore","slug":"the-json-property-name-should-only-be-configured-o","errorCode":null,"errorMessage":"The JSON property name should only be configured on nested owned navigations.","messagePattern":"The JSON property name should only be configured on nested owned navigations\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Extensions/RelationalOwnedNavigationBuilderExtensions.cs","lineNumber":132,"sourceCode":"        return builder;\n    }\n\n    /// <summary>\n    ///     Configures the navigation of an entity mapped to a JSON column, mapping the navigation to a specific JSON property,\n    ///     rather than using the navigation name.\n    /// </summary>\n    /// <param name=\"navigationBuilder\">The builder for the navigation being configured.</param>\n    /// <param name=\"name\">JSON property name to be used.</param>\n    /// <returns>The same builder instance so that multiple calls can be chained.</returns>\n    public static OwnedNavigationBuilder HasJsonPropertyName(\n        this OwnedNavigationBuilder navigationBuilder,\n        string? name)\n    {\n        Check.NullButNotEmpty(name);\n\n        if (!navigationBuilder.Metadata.PrincipalEntityType.IsOwned())\n        {\n            throw new InvalidOperationException(\n                RelationalStrings.JsonPropertyNameShouldBeConfiguredOnNestedNavigation);\n        }\n\n        navigationBuilder.Metadata.DeclaringEntityType.SetJsonPropertyName(name);\n\n        return navigationBuilder;\n    }\n\n    /// <summary>\n    ///     Configures the navigation of an entity mapped to a JSON column, mapping the navigation to a specific JSON property,\n    ///     rather than using the navigation name.\n    /// </summary>\n    /// <param name=\"navigationBuilder\">The builder for the navigation being configured.</param>\n    /// <param name=\"name\">JSON property name to be used.</param>\n    /// <returns>The same builder instance so that multiple calls can be chained.</returns>\n    public static OwnedNavigationBuilder<TSource, TTarget> HasJsonPropertyName<TSource, TTarget>(\n        this OwnedNavigationBuilder<TSource, TTarget> navigationBuilder,\n        string? name)","sourceCodeStart":114,"sourceCodeEnd":150,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.Relational/Extensions/RelationalOwnedNavigationBuilderExtensions.cs#L114-L150","documentation":"HasJsonPropertyName configures the JSON property name for an owned navigation. EF Core requires the navigation's PrincipalEntityType to itself be owned (IsOwned()), because JSON property names are only meaningful on nested owned navigations within a JSON column. Configuring it on a top-level or non-owned navigation throws.","triggerScenarios":"Calling navigationBuilder.HasJsonPropertyName(name) where navigationBuilder.Metadata.PrincipalEntityType.IsOwned() returns false — i.e. the containing entity is not an owned type participating in a JSON mapping.","commonSituations":"Calling HasJsonPropertyName on a top-level entity's navigation instead of a nested owned one; configuring JSON mapping before marking the type as owned; refactoring ownership without revisiting JSON config.","solutions":["Ensure the principal entity type is owned (OwnsOne / OwnsMany) before setting the JSON property name.","Move the HasJsonPropertyName call into the nested owned-navigation configuration chain.","Configure the JSON column mapping (ToJson) on the outermost owned navigation first."],"exampleFix":"// before\nmodelBuilder.Entity<Order>().Navigation(o => o.Details).HasJsonPropertyName(\"details\");\n// after\nmodelBuilder.Entity<Order>().OwnsOne(o => o.Details, nb => nb.ToJson(\"details\").HasJsonPropertyName(\"details\"));","handlingStrategy":"validation","validationCode":"// Ensure the principal entity type is owned before configuring JSON property name.\nif (!navigationBuilder.Metadata.PrincipalEntityType.IsOwned())\n{\n    // configure ownership (OwnsOne/OwnsMany) first, or skip HasJsonPropertyName.\n    return;\n}\nnavigationBuilder.HasJsonPropertyName(name);","typeGuard":"static bool IsNestedOwnedNavigation(OwnedNavigationBuilder nb)\n    => nb.Metadata.PrincipalEntityType.IsOwned();","tryCatchPattern":"try { navigationBuilder.HasJsonPropertyName(name); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"JSON property name\"))\n{ /* principal not owned; configure OwnsOne/ToJson first */ }","preventionTips":["Always configure OwnsOne/OwnsMany and ToJson before HasJsonPropertyName.","Keep JSON property name config inside the nested owned-navigation builder chain.","Write a model test asserting HasJsonPropertyName calls are on owned types."],"tags":["json-mapping","owned-navigation","model-builder","configuration"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}