dotnet/efcore · error · InvalidOperationException

The key {keyProperties} on the entity type '{entityType}' ca

Error message

The key {keyProperties} on the entity type '{entityType}' cannot be configured because the property '{property}' is contained in a complex type mapped to a JSON column. Keys cannot reference properties that are stored inside a JSON document.

What it means

ValidateKey (RelationalModelValidator.cs:223-234) throws when any property participating in a key is declared on a complex type that is mapped to a JSON column. Keys must be addressable as standalone columns (for indexing, FKs, joins), but properties inside a JSON document are embedded and cannot back a key, so the configuration is rejected.

Source

Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:228

        {
            throw new InvalidOperationException(
                RelationalStrings.AutoLoadedJsonProperty(property.Name, structuralType.DisplayName()));
        }
    }

    /// <inheritdoc />
    protected override void ValidateKey(
        IKey key,
        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
    {
        base.ValidateKey(key, logger);

        foreach (var property in key.Properties)
        {
            if (property.DeclaringType is IComplexType complexType
                && complexType.IsMappedToJson())
            {
                throw new InvalidOperationException(
                    RelationalStrings.KeyPropertyInJsonComplexType(
                        key.Properties.Format(),
                        key.DeclaringEntityType.DisplayName(),
                        property.Name));
            }
        }

        ValidateDefaultValuesOnKey(key, logger);
        ValidateValueGeneration(key, logger);
    }

    /// <summary>
    ///     Validates a primitive collection property.
    /// </summary>
    /// <param name="property">The property to validate.</param>
    /// <param name="logger">The logger to use.</param>
    protected override void ValidatePrimitiveCollection(
        IProperty property,

View on GitHub (pinned to dbf9771522)

Solutions

  1. Move the key property out of the JSON-mapped complex type onto the owning entity as a real column.
  2. If the owned type genuinely needs identity, stop mapping it to JSON and map it to its own table or as table-splitting columns.
  3. Remove the key configuration that references the JSON-contained property and let EF treat the owned type as a value object.

Example fix

// before
modelBuilder.Entity<Customer>().OwnsOne(c => c.Profile, p =>
{
    p.ToJson("ProfileJson");
});
modelBuilder.Entity<Customer>().HasKey(c => new { c.Id, c.Profile.ProfileId }); // ProfileId is in JSON -> throws

// after - promote the key column out of JSON
modelBuilder.Entity<Customer>().Property(c => c.ProfileId).HasColumnName("ProfileId");
modelBuilder.Entity<Customer>().HasKey(c => new { c.Id, c.ProfileId });
Defensive patterns

Strategy: validation

Validate before calling

// Pre-validate: no key property may live in a JSON-mapped complex type.
foreach (var et in context.Model.GetEntityTypes())
{
    foreach (var key in et.GetDeclaredKeys())
    {
        foreach (var p in key.Properties)
        {
            if (p.DeclaringType is IComplexType ct && ct.IsMappedToJson())
            {
                // will throw - move this property out of JSON.
            }
        }
    }
}

Prevention

When it happens

Trigger: Declaring a key on an entity type that references a property which itself lives inside a JSON-mapped complex type (e.g. an owned JSON type exposes an Id that you tried to make part of the owner's key). Thrown during model validation.

Common situations: Trying to define a composite key that includes an owned JSON entity's Id; refactoring an owned type from table-splitting to JSON while a key reference remained; key conventions picking up a JSON-owned property.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/9244b03da75a397b. Report an issue: GitHub.