dotnet/efcore · error · InvalidOperationException

The index {indexProperties} on the entity type '{entityType}

Error message

The index {indexProperties} on the entity type '{entityType}' cannot be configured because its properties are mapped to different JSON columns ('{firstColumn}' and '{secondColumn}'). All leaves of a JSON-path index (an index whose properties traverse a complex collection) must be contained in a single JSON column.

What it means

Thrown during JSON-path index validation when two index properties in the same index are mapped to different JSON columns. EF requires all leaves of a JSON-path index (an index traversing a complex collection) to share a single JSON container column so the database can create one functional/JSON index. See RelationalModelValidator.cs:2730-2742 where firstContainer differs from the current property's container.

Source

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

                if (index.CollectionIndices?[i] is not null)
                {
                    throw new InvalidOperationException(
                        RelationalStrings.JsonPathIndexPropertyMissingJsonColumn(
                            index.Properties.Format(),
                            index.DeclaringEntityType.DisplayName(),
                            property.Name));
                }

                continue;
            }

            if (firstContainer is null)
            {
                firstContainer = container;
            }
            else if (!string.Equals(firstContainer, container, StringComparison.Ordinal))
            {
                throw new InvalidOperationException(
                    RelationalStrings.JsonPathIndexPropertiesInDifferentJsonColumns(
                        index.Properties.Format(),
                        index.DeclaringEntityType.DisplayName(),
                        firstContainer,
                        container));
            }
        }
    }

    /// <inheritdoc />
    protected override void ValidateIndexProperty(
        IIndex index,
        IPropertyBase property,
        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
    {
        // A property declared inside a JSON-mapped complex type is a valid index target: when the
        // path traverses a collection the index is a JSON-path index (CollectionIndices is non-null,
        // already enforced by Index construction); otherwise it's a scalar inside a JSON document.

View on GitHub (pinned to dbf9771522)

Solutions

  1. Split the index into separate single-column indexes, one per JSON column.
  2. Restructure so all indexed properties live under the same JSON column.
  3. Remove properties from the index that belong to a different JSON column.

Example fix

// before: composite index spans two different JSON columns
modelBuilder.Entity<Person>()
    .ComplexProperty(p => p.HomeAddresses, ab => ab.ToJson("home_json"))
    .ComplexProperty(p => p.WorkAddresses, ab => ab.ToJson("work_json"));
modelBuilder.Entity<Person>().HasIndex("HomeAddresses.Zip", "WorkAddresses.Zip"); // throws

// after: separate indexes per JSON column
modelBuilder.Entity<Person>().HasIndex("HomeAddresses.Zip");
modelBuilder.Entity<Person>().HasIndex("WorkAddresses.Zip");
Defensive patterns

Strategy: validation

Validate before calling

// Check that all JSON-path index properties share one JSON container.
foreach (var index in modelBuilder.Model.GetEntityTypes().SelectMany(e => e.GetDeclaredIndexes()))
{
    if (index.CollectionIndices is null) continue;
    var containers = new HashSet<string>();
    for (var i = 0; i < index.Properties.Count; i++)
    {
        if (index.CollectionIndices[i] is null) continue;
        var prop = index.Properties[i];
        var c = (prop.DeclaringType as IComplexType)?.GetContainerColumnName();
        if (c != null) containers.Add(c);
    }
    if (containers.Count > 1)
        Console.WriteLine($"Index on {index.DeclaringEntityType.DisplayName()} spans multiple JSON columns: {string.Join(", ", containers)}");
}

Prevention

When it happens

Trigger: Calling HasIndex with multiple properties where each traverses a different complex collection that is mapped to a different ToJson column. The validator records the first JSON container name, then throws when it encounters a second property whose GetContainerColumnName() returns a different name.

Common situations: An entity has two JSON columns (e.g., 'HomeAddress' and 'WorkAddress') each containing collections, and the developer tries to create a composite index spanning properties from both JSON documents.

Related errors


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