dotnet/efcore · error · InvalidOperationException

A seed entity for entity type

Error message

A seed entity for entity type '{entityType}' has the same key value as another seed entity mapped to the same table '{table}'. Key values should be unique across seed entities. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the conflicting values.

What it means

Thrown by MigrationsModelDiffer while diffing the model to build seed-data modification commands. Two seed entities that map to the same (non-shared) table resolve to the same key, so EF cannot decide which row to insert/update. The non-sensitive form deliberately omits the key value so that data is not leaked into logs; enable EnableSensitiveDataLogging to see it.

Solutions

  1. Inspect every HasData block for the named entity type and make each key value unique.
  2. Temporarily call optionsBuilder.EnableSensitiveDataLogging() to print the conflicting key value and locate both entries.
  3. If the collision is intentional (merge), remove one of the duplicate seed entries so only one row is produced.
  4. For shared-table mappings confirm you actually intend one row; otherwise split the entities onto different tables.

Example fix

// before
modelBuilder.Entity<Customer>()
    .HasData(
        new Customer { Id = 1, Name = "Acme" },
        new Customer { Id = 1, Name = "Globex" }); // duplicate Id

// after
modelBuilder.Entity<Customer>()
    .HasData(
        new Customer { Id = 1, Name = "Acme" },
        new Customer { Id = 2, Name = "Globex" });
Defensive patterns

Strategy: validation

Validate before calling

// Before calling HasData, assert key uniqueness per entity type
static void AssertSeedKeysUnique<TEntity>(
    IEnumerable<TEntity> seed,
    Func<TEntity, object> keySelector)
{
    var dupes = seed.GroupBy(keySelector)
                    .Where(g => g.Count() > 1)
                    .ToList();
    if (dupes.Count > 0)
        throw new InvalidOperationException(
            $"Duplicate seed keys for {typeof(TEntity).Name}: " +
            string.Join(", ", dupes.Select(g => g.Key)));
}

// usage in OnModelCreating
AssertSeedKeysUnique(customers, c => c.Id);

Type guard

// Narrow anonymous seed rows to a distinct-by-key set before HasData
static T[] DistinctByKey<T, TKey>(IEnumerable<T> src, Func<T, TKey> key)
    => src.GroupBy(key).Select(g => g.First()).ToArray();

Prevention

When it happens

Trigger: ModelCreating HasData(...) for one entity type contains two entries whose key properties evaluate equal, or two entity types mapped to the same table seed colliding keys. Reached when 'dotnet ef migrations add' (or any code path that runs the differ) processes the model.

Common situations: Copy-pasted seed rows with unchanged Id; integer key constants that collide; TPH inheritance where base and derived entities seed the same discriminator key; seeding regenerated after a key-column rename where old seed values were not updated.

Related errors


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

Appendix: source

Thrown at src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs:1936

                if (!keyFound)
                {
                    continue;
                }

                if (identityMap.FindCommand(key) is { } existingCommand)
                {
                    if (!table.IsShared)
                    {
                        if (sensitiveLoggingEnabled)
                        {
                            throw new InvalidOperationException(
                                RelationalStrings.DuplicateSeedDataSensitive(
                                    entityType.DisplayName(),
                                    BuildValuesString(key),
                                    table.SchemaQualifiedName));
                        }

                        throw new InvalidOperationException(
                            RelationalStrings.DuplicateSeedData(
                                entityType.DisplayName(),
                                table.SchemaQualifiedName));
                    }

                    command = existingCommand;
                }
                else
                {
                    command = CommandBatchPreparerDependencies.ModificationCommandFactory.CreateNonTrackedModificationCommand(
                        new NonTrackedModificationCommandParameters(table, sensitiveLoggingEnabled));
                    command.EntityState = initialState;

                    identityMap.Add(key, command);
                }

                foreach (var columnMapping in mapping.ColumnMappings)
                {

View on GitHub (pinned to 3a2006ef56)