dotnet/efcore · error · InvalidOperationException

The indexes on ' ' and on ' ' are both mapped to ' . ', but…

Error message

The indexes {index1} on '{entityType1}' and {index2} on '{entityType2}' are both mapped to '{table}.{indexName}', but with different uniqueness configurations.

What it means

Two indexes share the same database name and table but one is unique and the other is not. Uniqueness is a fundamental index property and cannot differ for a single database object.

Solutions

  1. Decide whether the index should be unique and set both definitions to match.
  2. Give the indexes distinct database names via HasDatabaseName.
  3. Remove the conflicting index.
  4. Move one entity to its own table so the indexes no longer collide.

Example fix

// before
modelBuilder.Entity<User>().HasIndex(u => u.Email).IsUnique().HasDatabaseName("IX_User_Email");
modelBuilder.Entity<UserAudit>().ToTable("User").HasIndex(u => u.Email).HasDatabaseName("IX_User_Email");

// after: align uniqueness or rename
modelBuilder.Entity<UserAudit>().ToTable("User").HasIndex(u => u.Email).IsUnique().HasDatabaseName("IX_User_Email");
Defensive patterns

Strategy: validation

Validate before calling

// Detect uniqueness mismatch for colliding index names on the same table.
var groups = modelBuilder.Model.GetEntityTypes()
    .SelectMany(e => e.GetDeclaredIndexes())
    .GroupBy(i => new { Name = i.GetDatabaseName(), Table = i.DeclaringEntityType.GetSchemaQualifiedTableName() })
    .Where(g => g.Count() > 1);
foreach (var g in groups)
{
    if (g.Select(i => i.IsUnique).Distinct().Count() > 1)
        Console.WriteLine($"Index '{g.Key.Name}' on '{g.Key.Table}' has conflicting uniqueness.");
}

Prevention

When it happens

Trigger: RelationalIndexExtensions.AreCompatible with shouldThrow:true when index.IsUnique != duplicateIndex.IsUnique. Commonly from table-splitting where one entity declares a unique index and another declares a non-unique index under the same name on the shared table.

Common situations: Owner declares IsUnique(false) and an owned/partner entity declares IsUnique(true) under a colliding name; copy/paste of HasDatabaseName after toggling uniqueness; legacy index conventions interacting with new unique indexes.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/344f9171d67d97bc. Report an issue: GitHub.

Appendix: source

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

        if (!columnNames.SequenceEqual(duplicateColumnNames))
        {
            return shouldThrow
                ? throw new InvalidOperationException(
                    RelationalStrings.DuplicateIndexColumnMismatch(
                        index.DisplayName(),
                        index.DeclaringEntityType.DisplayName(),
                        duplicateIndex.DisplayName(),
                        duplicateIndex.DeclaringEntityType.DisplayName(),
                        index.DeclaringEntityType.GetSchemaQualifiedTableName(),
                        index.GetDatabaseName(storeObject),
                        FormatColumnNames(columnNames),
                        FormatColumnNames(duplicateColumnNames)))
                : false;
        }

        return index.IsUnique != duplicateIndex.IsUnique
            ? shouldThrow
                ? throw new InvalidOperationException(
                    RelationalStrings.DuplicateIndexUniquenessMismatch(
                        index.DisplayName(),
                        index.DeclaringEntityType.DisplayName(),
                        duplicateIndex.DisplayName(),
                        duplicateIndex.DeclaringEntityType.DisplayName(),
                        index.DeclaringEntityType.GetSchemaQualifiedTableName(),
                        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(),

View on GitHub (pinned to 3a2006ef56)