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 configured with different delete behavior ('{deleteBehavior1}' and '{deleteBehavior2}'). What it means
Thrown by AreCompatible when two foreign keys share name and all column/table configuration but specify different DeleteBehavior that maps to different referential actions. A single FK constraint can carry only one ON DELETE action, so conflicting actions (e.g. Cascade vs Restrict) cannot be merged.
Source
Thrown at src/EFCore.Relational/Metadata/Internal/RelationalForeignKeyExtensions.cs:132
if (foreignKey.IsUnique != duplicateForeignKey.IsUnique)
{
return shouldThrow
? throw new InvalidOperationException(
RelationalStrings.DuplicateForeignKeyUniquenessMismatch(
foreignKey.Properties.Format(),
foreignKey.DeclaringEntityType.DisplayName(),
duplicateForeignKey.Properties.Format(),
duplicateForeignKey.DeclaringEntityType.DisplayName(),
foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),
foreignKey.GetConstraintName(storeObject, principalTable.Value)))
: false;
}
var referentialAction = RelationalModel.ToReferentialAction(foreignKey.DeleteBehavior);
var duplicateReferentialAction = RelationalModel.ToReferentialAction(duplicateForeignKey.DeleteBehavior);
return referentialAction != duplicateReferentialAction
? shouldThrow
? throw new InvalidOperationException(
RelationalStrings.DuplicateForeignKeyDeleteBehaviorMismatch(
foreignKey.Properties.Format(),
foreignKey.DeclaringEntityType.DisplayName(),
duplicateForeignKey.Properties.Format(),
duplicateForeignKey.DeclaringEntityType.DisplayName(),
foreignKey.DeclaringEntityType.GetSchemaQualifiedTableName(),
foreignKey.GetConstraintName(storeObject, principalTable.Value),
referentialAction,
duplicateReferentialAction))
: false
: foreignKey.IsExcludedFromMigrations() == duplicateForeignKey.IsExcludedFromMigrations()
|| (shouldThrow
? throw new InvalidOperationException(
RelationalStrings.DuplicateForeignKeyExcludedFromMigrationsMismatch(
foreignKey.Properties.Format(),
foreignKey.DeclaringEntityType.DisplayName(),
duplicateForeignKey.Properties.Format(),
duplicateForeignKey.DeclaringEntityType.DisplayName(),View on GitHub (pinned to dbf9771522)
Solutions
- Make the OnDelete values consistent across the colliding FKs (same ReferentialAction).
- Give the FKs distinct HasConstraintName values when delete behavior must differ.
- Decide on a single delete policy for the shared constraint and apply it to both.
- Verify ReferentialAction mapping if using NoAction vs Restrict intentionally.
Example fix
// before
modelBuilder.Entity<Invoice>().HasOne(i => i.Customer)
.WithMany().HasForeignKey(i => i.CustomerId)
.OnDelete(DeleteBehavior.Cascade).HasConstraintName("FK_Inv_Cust");
modelBuilder.Entity<Invoice>().HasOne(i => i.BillingCustomer)
.WithMany().HasForeignKey(i => i.CustomerId)
.OnDelete(DeleteBehavior.Restrict).HasConstraintName("FK_Inv_Cust");
// after
modelBuilder.Entity<Invoice>().HasOne(i => i.BillingCustomer)
.WithMany().HasForeignKey(i => i.CustomerId)
.OnDelete(DeleteBehavior.Restrict).HasConstraintName("FK_Inv_Cust_Billing"); Defensive patterns
Strategy: validation
Validate before calling
// Verify FKs sharing a name resolve to the same referential action
foreach (var g in allFks.GroupBy(fk => fk.GetConstraintName()))
{
var actions = g.Select(fk => RelationalModel.ToReferentialAction(fk.DeleteBehavior)).Distinct();
if (actions.Count() > 1)
throw new InvalidOperationException($"FK {g.Key} has mismatched delete behavior.");
} Prevention
- Standardize OnDelete for FKs that share a constraint name.
- When overriding OnDelete on one type in a shared table, also rename the constraint.
- Remember Restrict and NoAction may map to the same action and not collide.
When it happens
Trigger: Two sharing-table FKs with the same constraint name but different OnDelete(...) values whose ReferentialAction mappings differ (Cascade vs SetNull vs Restrict vs NoAction). Note: behaviors that map to the same action (e.g. Restrict and NoAction both to NO ACTION) do not throw.
Common situations: TPH/table-splitting where base and derived relationships over the same FK configure different delete behaviors. Inheriting a Cascade FK and overriding to Restrict on one type while reusing the name.
Related errors
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
- The foreign keys {foreignKeyProperties1} on '{entityType1}'
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/86f1220ceb3cd98f.
Report an issue: GitHub.