dotnet/efcore · error · InvalidOperationException
The keys on ' ' and on ' ' are both mapped to ' . ', but…
Error message
The keys {keyProperties1} on '{entityType1}' and {keyProperties2} on '{entityType2}' are both mapped to '{table}.{keyName}', but with different columns ({columnNames1} and {columnNames2}). What it means
Two keys share the same database name and table but map to different columns. A single key constraint name cannot identify two different column sets.
Solutions
- Give each key a distinct name via HasName(...).
- Map both keys to the same columns if they are meant to be the same constraint.
- Remove the redundant key.
- Audit HasName usages across entities that share a table.
Example fix
// before
modelBuilder.Entity<Order>().HasKey(o => o.Id).HasName("PK_Order");
modelBuilder.Entity<OrderSnapshot>().ToTable("Order").HasKey(s => s.SnapshotId).HasName("PK_Order");
// after
modelBuilder.Entity<OrderSnapshot>().ToTable("Order").HasKey(s => s.SnapshotId).HasName("PK_Order_Snapshot"); Defensive patterns
Strategy: validation
Validate before calling
// Detect key-name collisions with differing columns on the same table.
var groups = modelBuilder.Model.GetEntityTypes()
.SelectMany(e => e.GetDeclaredKeys())
.GroupBy(k => new { Name = k.GetName(), Table = k.DeclaringEntityType.GetSchemaQualifiedTableName() })
.Where(g => g.Count() > 1);
foreach (var g in groups)
{
var cols = g.Select(k => string.Join(",", k.Properties.Select(p => p.GetColumnName()))).Distinct();
if (cols.Count() > 1)
Console.WriteLine($"Key '{g.Key.Name}' on '{g.Key.Table}' has conflicting columns.");
} Prevention
- Give keys distinct HasName when entities share a table but define different key shapes.
- Review key definitions during table-splitting setup.
- Validate the model in tests.
When it happens
Trigger: RelationalKeyExtensions.AreCompatible with shouldThrow:true when !columnNames.SequenceEqual(duplicateColumnNames). Triggered when two entities on the same table each define a key whose properties resolve to different columns under a shared constraint name.
Common situations: Table-splitting where the owner defines a PK and a partner entity defines an alternate key with a colliding name; explicit HasName copy/paste errors across different properties.
Related errors
- The indexes on ' ' and on ' ' are both mapped to ' . ', but…
- The keys on ' ' and on ' ' are both mapped to ' ', but on…
- Entity type ' ' has a split mapping for ' ', but it also…
- Entity type ' ' has a split mapping for ' ' that is shared…
- Entity type ' ' has a split mapping for ' ', but it doesn't…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/5ccb88433db5b3c7.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Metadata/Internal/RelationalKeyExtensions.cs:45
{
var columnNames = key.Properties.GetColumnNames(storeObject);
var duplicateColumnNames = duplicateKey.Properties.GetColumnNames(storeObject);
return columnNames == null
|| duplicateColumnNames == null
? shouldThrow
? throw new InvalidOperationException(
RelationalStrings.DuplicateKeyTableMismatch(
key.Properties.Format(),
key.DeclaringEntityType.DisplayName(),
duplicateKey.Properties.Format(),
duplicateKey.DeclaringEntityType.DisplayName(),
key.GetName(storeObject),
key.DeclaringEntityType.GetSchemaQualifiedTableName(),
duplicateKey.DeclaringEntityType.GetSchemaQualifiedTableName()))
: false
: columnNames.SequenceEqual(duplicateColumnNames)
|| (shouldThrow
? throw new InvalidOperationException(
RelationalStrings.DuplicateKeyColumnMismatch(
key.Properties.Format(),
key.DeclaringEntityType.DisplayName(),
duplicateKey.Properties.Format(),
duplicateKey.DeclaringEntityType.DisplayName(),
key.DeclaringEntityType.GetSchemaQualifiedTableName(),
key.GetName(storeObject),
key.Properties.FormatColumns(storeObject),
duplicateKey.Properties.FormatColumns(storeObject)))
: false);
}
/// <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
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>View on GitHub (pinned to 3a2006ef56)