dotnet/efcore · error · InvalidOperationException
Entity type ' ' has a split mapping and is an optional…
Error message
Entity type '{entityType}' has a split mapping and is an optional dependent sharing a store object, but it doesn't map any required non-shared property to the main store object. Keep at least one required non-shared property mapped to a column on '{storeObject}' or mark '{entityType}' as a required dependent by calling '{requiredDependentConfig}'. What it means
When the entity is an optional dependent that shares a store object (table splitting), an all-NULL row is indistinguishable from 'no dependent'. To disambiguate, the validator requires at least one REQUIRED (non-nullable), non-shared property mapped to the main store object. If none is found and a row-internal FK is not IsRequiredDependent, it throws and tells you how to mark the dependent required.
Solutions
- Add a required (non-nullable), non-shared property mapped to the main store object so a dependent row is always detectable.
- Mark the dependent as required exactly as the message suggests: modelBuilder.Entity<Principal>().OwnsOne(p => p.Dependent).Navigation(p => p.Dependent).IsRequired() (or HasPrincipalKey/required navigation) so IsRequiredDependent becomes true.
- Make an existing nullable column non-nullable if business rules allow.
Example fix
// before — optional dependent, all columns nullable -> [443]
modelBuilder.Entity<Order>()
.OwnsOne(o => o.BillingInfo, b =>
{
b.Property(bi => bi.TaxId).IsRequired(false);
b.ToTable("Order");
});
// after — mark the owned navigation required
modelBuilder.Entity<Order>()
.OwnsOne(o => o.BillingInfo, b =>
{
b.Property(bi => bi.TaxId).IsRequired();
b.ToTable("Order");
})
.Navigation(o => o.BillingInfo)
.IsRequired(); Defensive patterns
Strategy: validation
Validate before calling
// For an optional dependent sharing a table, ensure a required non-shared property OR mark required.
static bool OptionalDependentIsDistinguishable(IEntityType et, StoreObjectIdentifier main)
{
if (et.FindRowInternalForeignKeys(main).All(fk => fk.IsRequiredDependent))
return true;
return et.GetProperties().Any(p =>
!p.IsPrimaryKey()
&& !p.IsNullable
&& p.GetColumnName(main) is not null
&& p.FindSharedStoreObjectRootProperty(main) is null);
} Prevention
- Give optional dependents at least one non-nullable, non-shared column on the shared table.
- Prefer marking owned navigations required (.Navigation(...).IsRequired()) when the dependent always exists.
- Avoid all-nullable owned type column sets in table splitting.
When it happens
Trigger: An owned/dependent entity configured as optional (nullable navigation) that also uses split mapping, where every property on the main store object is either nullable or shared from the principal (FindSharedStoreObjectRootProperty != null), so nonSharedRequiredPropertyFound stays false.
Common situations: Nullable owned navigations in table splitting with only nullable columns; refactor that made all columns nullable; TPT/TPH sharing where dependent columns overlap the principal.
Related errors
- Entity type ' ' is an optional dependent using table…
- Entity type ' ' has a split mapping, but it doesn't map any…
- Entity type ' ' has a split mapping for ' ', but it doesn't…
- Entity type ' ' has a split mapping for ' ' that is shared…
- Entity type ' ' has a split mapping for ' ', but the…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/a806de288a1a16b9.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:2503
&& !property.IsNullable
&& property.FindSharedStoreObjectRootProperty(mainObject) == null)
{
nonSharedRequiredPropertyFound = true;
}
}
}
if (!propertyFound)
{
throw new InvalidOperationException(
RelationalStrings.EntitySplittingMissingPropertiesMainFragment(
entityType.DisplayName(), mainObject.DisplayName()));
}
if (!nonSharedRequiredPropertyFound)
{
var rowInternalFk = entityType.FindRowInternalForeignKeys(mainObject).First(fk => !fk.IsRequiredDependent);
throw new InvalidOperationException(
RelationalStrings.EntitySplittingMissingRequiredPropertiesOptionalDependent(
entityType.DisplayName(), mainObject.DisplayName(),
$".Navigation(p => p.{rowInternalFk.PrincipalToDependent!.Name}).IsRequired()"));
}
return mainObject;
}
}
/// <summary>
/// Validates a table-specific property override for a property.
/// </summary>
/// <param name="property">The property to validate.</param>
/// <param name="propertyOverride">The property override to validate.</param>
/// <param name="logger">The logger to use.</param>
protected virtual void ValidatePropertyOverride(
IProperty property,
IReadOnlyRelationalPropertyOverrides propertyOverride,View on GitHub (pinned to 3a2006ef56)