dotnet/efcore · error · InvalidOperationException
A seed entity for entity type
Error message
A seed entity for entity type '{entityType}' has the same key value {keyValue} as another seed entity mapped to the same table '{table}'. Key values should be unique across seed entities. What it means
During migration diffing, EF builds an identity map keyed by primary key per target table. For a non-shared table, encountering two seed entities with the same key is ambiguous and throws DuplicateSeedData, because the diff could not decide which seed wins.
Solutions
- Dedupe seed data: ensure each key value appears exactly once per entity type per table.
- When merging seeds from multiple modules, run a union/dedup pass keyed by primary key before HasData.
- Enable sensitive data logging to see the offending key value (DuplicateSeedDataSensitive message includes it).
- Re-run Add-Migration after correcting the seed data so the diff is regenerated.
Example fix
// before
modelBuilder.Entity<User>().HasData(
new User { Id = 1, Name = "Alice" },
new User { Id = 1, Name = "Bob" }); // duplicate key 1
// after
modelBuilder.Entity<User>().HasData(
new User { Id = 1, Name = "Alice" },
new User { Id = 2, Name = "Bob" }); Defensive patterns
Strategy: validation
Validate before calling
// Dedupe seed data by primary key before calling HasData.
var deduped = seedUsers
.GroupBy(u => u.Id)
.Select(g => g.First())
.ToArray();
modelBuilder.Entity<User>().HasData(deduped); Type guard
static bool HasUniqueKeys<T, TKey>(IEnumerable<T> rows, Func<T, TKey> keySelector)
=> rows.GroupBy(keySelector).All(g => g.Count() == 1); Prevention
- Dedupe seed collections by key before HasData.
- Enable sensitive data logging during development to surface the colliding key value.
- Merge seeds from multiple modules with a union-by-key step.
When it happens
Trigger: Two HasData calls (or one with two objects) seeding the same entity type with identical key values, both mapped to the same non-shared table; or re-seeding after a key change left duplicates.
Common situations: Copy-pasted seed rows; merging seed data from multiple configuration sources; key generators producing collisions; version upgrades that changed key computation (value converters) so previously-distinct seeds now collide.
Related errors
- values were provided in CreateIndexOperations.IsDescending…
- The computed column SQL has not been specified for the…
- The data deletion operation on
- The data modification operation on
- The default value has not been specified for the column
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/4815c2649fd40acf.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs:1929
var valueConverter = columnMapping.TypeMapping.Converter;
key[i] = NormalizeSeedValue(
valueConverter == null
? value
: valueConverter.ConvertToProvider(value));
}
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));View on GitHub (pinned to 3a2006ef56)