dotnet/efcore · error · InvalidOperationException
Entity type '{entityType}' has a split mapping for '{storeOb
Error message
Entity type '{entityType}' has a split mapping for '{storeObject}', but it doesn't map any non-primary key property to it. Map at least one non-primary key property to a column on '{storeObject}'. What it means
A split fragment must carry at least one NON-primary-key property; otherwise it adds a redundant store object with no real data. ValidateMappingFragment tracks propertiesFound while iterating properties and throws EntitySplittingMissingProperties if no non-PK property resolves to a column on the fragment.
Source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:2440
if (property.IsPrimaryKey())
{
throw new InvalidOperationException(
RelationalStrings.EntitySplittingMissingPrimaryKey(
entityType.DisplayName(), fragment.StoreObject.DisplayName()));
}
continue;
}
if (!property.IsPrimaryKey())
{
propertiesFound = true;
}
}
if (!propertiesFound)
{
throw new InvalidOperationException(
RelationalStrings.EntitySplittingMissingProperties(
entityType.DisplayName(), fragment.StoreObject.DisplayName()));
}
switch (fragment.StoreObject.StoreObjectType)
{
case StoreObjectType.Table:
anyTableFragments = true;
break;
case StoreObjectType.View:
anyViewFragments = true;
break;
}
}
if (anyTableFragments)
{
ValidateMainMapping(entityType, StoreObjectIdentifier.Create(entityType, StoreObjectType.Table)!.Value);View on GitHub (pinned to dbf9771522)
Solutions
- Move at least one non-key property onto the fragment: t.Property(c => c.LargeColumn).
- Remove the empty fragment entirely if it no longer holds any payload.
- If you only need the key, the split fragment serves no purpose - merge it back into the main table.
Example fix
// before
modelBuilder.Entity<Customer>().ToTable("Customers")
.SplitToTable("CustomerExtras", t =>
{
t.Property(c => c.Id).HasColumnName("CustomerId"); // only the key
});
// after
modelBuilder.Entity<Customer>().ToTable("Customers")
.SplitToTable("CustomerExtras", t =>
{
t.Property(c => c.Id).HasColumnName("CustomerId");
t.Property(c => c.Biography); // a non-key payload
}); Defensive patterns
Strategy: validation
Validate before calling
bool SplitFragmentsHavePayload(DbContext context)
{
foreach (var et in context.Model.GetEntityTypes())
foreach (var f in et.GetTableMappingFragments())
{
bool any = et.GetProperties().Any(p => !p.IsPrimaryKey() && p.GetColumnName(f.StoreObject) is not null);
if (!any) return false;
}
return true;
} Try / catch
try { _ = context.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("split mapping", StringComparison.Ordinal) && ex.Message.Contains("non-primary key", StringComparison.Ordinal) && !ex.Message.Contains("main store object", StringComparison.Ordinal))
{
throw new InvalidOperationException("A split fragment has no non-key property. Move at least one payload column onto it or remove the fragment.", ex);
} Prevention
- Ensure every .SplitToTable fragment carries at least one non-key property.
- Remove fragments you have emptied during refactoring.
- Validate the model in tests to catch payload-less fragments.
When it happens
Trigger: A .SplitToTable fragment only maps primary key columns (or maps nothing but the key). The loop sets propertiesFound only for non-PK properties with a column; if none are found, it throws.
Common situations: Adding a split fragment then moving all its non-key properties elsewhere or ignoring them; scaffolding splits that ended up empty after manual trimming; refactoring that left a fragment with only the join key.
Related errors
- Entity type '{entityType}' has a split mapping for '{storeOb
- Entity type '{entityType}' has a split mapping for '{storeOb
- Entity type '{entityType}' has a split mapping for '{storeOb
- Entity type '{entityType}' has a split mapping for '{storeOb
- Entity type '{entityType}' has a split mapping for '{storeOb
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/030f5e3f724b92d7.
Report an issue: GitHub.