dotnet/efcore · error · InvalidOperationException

The foreign keys {foreignKeyProperties1} on '{entityType1}'

Error message

The foreign keys {foreignKeyProperties1} on '{entityType1}' and {foreignKeyProperties2} on '{entityType2}' are both mapped to '{table}.{foreignKeyName}', but referencing different principal columns ({principalColumnNames1} and {principalColumnNames2}).

What it means

Thrown by AreCompatible when two foreign keys share name, tables, and dependent columns, but the principal-side referenced columns differ. The single FK constraint can target only one principal column set, so the mismatch is rejected.

Source

Thrown at src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs:101

        {
            return shouldThrow
                ? throw new InvalidOperationException(
                    RelationalStrings.DuplicateForeignKeyColumnMismatch(
                        foreignKey.Properties.Format(),
                        foreignKey.DeclaringEntityType.DisplayName(),
                        duplicateForeignKey.Properties.Format(),
                        duplicateForeignKey.DeclaringEntityType.DisplayName(),
                        foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),
                        foreignKey.GetConstraintName(storeObject, principalTable.Value),
                        foreignKey.Properties.FormatColumns(storeObject),
                        duplicateForeignKey.Properties.FormatColumns(storeObject)))
                : false;
        }

        if (!principalColumns.SequenceEqual(duplicatePrincipalColumns))
        {
            return shouldThrow
                ? throw new InvalidOperationException(
                    RelationalStrings.DuplicateForeignKeyPrincipalColumnMismatch(
                        foreignKey.Properties.Format(),
                        foreignKey.DeclaringEntityType.DisplayName(),
                        duplicateForeignKey.Properties.Format(),
                        duplicateForeignKey.DeclaringEntityType.DisplayName(),
                        foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),
                        foreignKey.GetConstraintName(storeObject, principalTable.Value),
                        foreignKey.PrincipalKey.Properties.FormatColumns(principalTable.Value),
                        duplicateForeignKey.PrincipalKey.Properties.FormatColumns(principalTable.Value)))
                : false;
        }

        if (foreignKey.IsUnique != duplicateForeignKey.IsUnique)
        {
            return shouldThrow
                ? throw new InvalidOperationException(
                    RelationalStrings.DuplicateForeignKeyUniquenessMismatch(
                        foreignKey.Properties.Format(),

View on GitHub (pinned to dbf9771522)

Solutions

  1. Make both FKs reference the same principal key (same principal columns).
  2. Assign distinct HasConstraintName values so each FK targets its own principal key.
  3. Verify HasPrincipalKey configuration is consistent across the colliding FKs.
  4. Audit principal column names via PrincipalKey.Properties.GetColumnNames.

Example fix

// before (one FK targets PK Id, the other targets alt key Code, same name)
modelBuilder.Entity<Order>().HasOne(o => o.Customer)
    .WithMany().HasForeignKey(o => o.CustomerId).HasConstraintName("FK_Order_Customer");
modelBuilder.Entity<Order>().HasOne(o => o.CustomerByCode)
    .WithMany().HasForeignKey(o => o.CustomerCode)
    .HasPrincipalKey(c => c.Code).HasConstraintName("FK_Order_Customer");

// after
modelBuilder.Entity<Order>().HasOne(o => o.CustomerByCode)
    .WithMany().HasForeignKey(o => o.CustomerCode)
    .HasPrincipalKey(c => c.Code).HasConstraintName("FK_Order_Customer_Code");
Defensive patterns

Strategy: validation

Validate before calling

// Verify FKs sharing a name reference the same principal key columns
foreach (var g in allFks.GroupBy(fk => fk.GetConstraintName()))
{
    var principalCols = g.Select(fk => string.Join(",", fk.PrincipalKey.Properties.GetColumnNames(store))).Distinct();
    if (principalCols.Count() > 1)
        throw new InvalidOperationException($"FK {g.Key} references different principal columns.");
}

Prevention

When it happens

Trigger: Two same-named FKs point at the same principal table but reference different principal columns — e.g. one targets the primary key and another targets an alternate key, yet both got the same constraint name.

Common situations: Switching a FK from referencing the PK to an alternate key (HasPrincipalKey) without renaming the constraint. TPH/table-splitting where shared FKs disagree on the principal key.

Related errors


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