dotnet/efcore · error · InvalidOperationException

The indexes {index1} on '{entityType1}' and {index2} on '{en

Error message

The indexes {index1} on '{entityType1}' and {index2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different filters ('{filter1}' and '{filter2}').

What it means

Thrown by RelationalIndexExtensions.AreCompatible when two same-named indexes on the same table match on columns, uniqueness, and sort order but disagree on the SQL filter (GetFilter). Because a filtered index is one physical object, EF rejects conflicting HasFilter values under one name.

Source

Thrown at src/EFCore.Relational/Metadata/Internal/RelationalIndexExtensions.cs:110

                        index.GetDatabaseName(storeObject)))
                : false
            : (index.IsDescending is null) != (duplicateIndex.IsDescending is null)
            || (index.IsDescending is not null
                && duplicateIndex.IsDescending is not null
                && !index.IsDescending.SequenceEqual(duplicateIndex.IsDescending))
                ? shouldThrow
                    ? throw new InvalidOperationException(
                        RelationalStrings.DuplicateIndexSortOrdersMismatch(
                            index.DisplayName(),
                            index.DeclaringEntityType.DisplayName(),
                            duplicateIndex.DisplayName(),
                            duplicateIndex.DeclaringEntityType.DisplayName(),
                            index.DeclaringEntityType.GetSchemaQualifiedTableName(),
                            index.GetDatabaseName(storeObject)))
                    : false
                : index.GetFilter(storeObject) == duplicateIndex.GetFilter(storeObject)
                || (shouldThrow
                    ? throw new InvalidOperationException(
                        RelationalStrings.DuplicateIndexFiltersMismatch(
                            index.DisplayName(),
                            index.DeclaringEntityType.DisplayName(),
                            duplicateIndex.DisplayName(),
                            duplicateIndex.DeclaringEntityType.DisplayName(),
                            index.DeclaringEntityType.GetSchemaQualifiedTableName(),
                            index.GetDatabaseName(storeObject),
                            index.GetFilter(),
                            duplicateIndex.GetFilter()))
                    : false);
    }

    private static string FormatColumnNames(IEnumerable<string> columnNames)
        => "{" + string.Join(", ", columnNames.Select(n => "'" + n + "'")) + "}";

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in

View on GitHub (pinned to dbf9771522)

Solutions

  1. Apply the identical HasFilter SQL on every index sharing the database name.
  2. Remove the HasFilter from both so the index becomes unfiltered consistently.
  3. If filters must differ, give the indexes distinct HasDatabaseName values.

Example fix

// before
modelBuilder.Entity<Doc>().HasIndex(d => d.Title).HasFilter("[Title] IS NOT NULL").HasDatabaseName("IX_Title");
modelBuilder.Entity<Archive>().HasIndex(a => a.Title).HasDatabaseName("IX_Title"); // unfiltered -> throws

// after
modelBuilder.Entity<Archive>().HasIndex(a => a.Title).HasFilter("[Title] IS NOT NULL").HasDatabaseName("IX_Title");
Defensive patterns

Strategy: validation

Validate before calling

// Detect HasFilter mismatches among same-named indexes
var bad = model.GetEntityTypes()
    .SelectMany(e => e.GetDeclaredIndexes())
    .GroupBy(i => i.GetDatabaseName())
    .Where(g => g.Select(i => i.GetFilter() ?? "").Distinct().Count() > 1)
    .Select(g => g.Key);
if (bad.Any()) throw new InvalidOperationException("Filter mismatch: " + string.Join(", ", bad));

Prevention

When it happens

Trigger: Line 108-119: index.GetFilter(storeObject) != duplicateIndex.GetFilter(storeObject). Produced when HasFilter("...") is set on one HasIndex but not, or differently, on a colliding index across table-sharing entity types.

Common situations: Soft-delete columns where one entity filters out deleted rows and the co-mapped entity does not; SQL Server filtered indexes declared on one entity only; cross-provider migrations where a filter string was provider-specific and drifted.

Related errors


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