dotnet/efcore · error · InvalidOperationException
Table name must be specified to configure a table-specific p
Error message
Table name must be specified to configure a table-specific property mapping.
What it means
Thrown by OwnedNavigationTableBuilder.GetStoreObjectIdentifier() at OwnedNavigationTableBuilder.cs:164 when the StoreObject property is null. This occurs when a table-specific property mapping is attempted on an owned navigation table builder that was not created with a specific table name (i.e., no ToTable call established the fragment).
Source
Thrown at src/EFCore.Relational/Metadata/Builders/OwnedNavigationTableBuilder.cs:164
/// <summary>
/// Maps the property to a column on the current table and returns an object that can be used
/// to provide table-specific configuration if the property is mapped to more than one table.
/// </summary>
/// <typeparam name="TProperty">The type of the property to be configured.</typeparam>
/// <param name="propertyName">The name of the property to be configured.</param>
/// <returns>An object that can be used to configure the property.</returns>
public virtual ColumnBuilder<TProperty> Property<TProperty>(string propertyName)
=> new(GetStoreObjectIdentifier(), OwnedNavigationBuilder.Property<TProperty>(propertyName));
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
[EntityFrameworkInternal]
protected virtual StoreObjectIdentifier GetStoreObjectIdentifier()
=> StoreObject ?? throw new InvalidOperationException(RelationalStrings.MappingFragmentMissingName);
OwnedNavigationBuilder IInfrastructure<OwnedNavigationBuilder>.Instance
=> OwnedNavigationBuilder;
#region Hidden System.Object members
/// <summary>
/// Returns a string that represents the current object.
/// </summary>
/// <returns>A string that represents the current object.</returns>
[EditorBrowsable(EditorBrowsableState.Never)]
public override string? ToString()
=> base.ToString();
/// <summary>
/// Determines whether the specified object is equal to the current object.
/// </summary>
/// <param name="obj">The object to compare with the current object.</param>View on GitHub (pinned to dbf9771522)
Solutions
- Ensure the owned navigation is mapped to a specific table via .ToTable("TableName") before calling table-specific property configuration.
- Use the non-table-specific Property configuration directly on the owned navigation builder if you don't need per-table overrides.
Example fix
// before: no table specified
modelBuilder.Entity<Order>()
.OwnsOne(o => o.Details, ob =>
{
// attempt table-specific override without a named table
ob.ToTable("OrderDetails")
.Property(d => d.Notes)
.HasColumnName("d_notes");
});
// If the builder somehow has no StoreObject, ensure ToTable is called first.
// after: always chain from the ToTable result
modelBuilder.Entity<Order>()
.OwnsOne(o => o.Details, ob =>
{
ob.ToTable("OrderDetails", tb =>
{
tb.Property(d => d.Notes).HasColumnName("d_notes");
});
}); Defensive patterns
Strategy: validation
Validate before calling
// Ensure the OwnedNavigationTableBuilder has a store object before calling Property()
// Always chain from the ToTable callback:
modelBuilder.Entity<Order>().OwnsOne(o => o.Details, ob =>
{
ob.ToTable("OrderDetails", tb =>
{
// 'tb' has a valid StoreObject here
tb.Property(d => d.Notes).HasColumnName("d_notes");
});
}); Prevention
- Always configure table-specific property overrides inside the ToTable(name, tb => {...}) callback.
- Never store a TableBuilder reference and use it outside the callback scope.
When it happens
Trigger: Calling .Property<T>("ColName").HasColumnName(...) on an OwnedNavigationTableBuilder whose StoreObject is null — this happens when the builder was obtained without specifying a table, e.g., via an API path that doesn't pass a StoreObjectIdentifier.
Common situations: Attempting to override column mappings for a specific table on an owned navigation that hasn't been mapped to a named table fragment. Misusing the builder API by calling table-specific configuration before ToTable.
Related errors
- Table name must be specified to configure a table-specific p
- Invalid number of index sort order values: {numValues} value
- IsDescending and AllDescending cannot both be specified on t
- The number argument cannot be a negative number.
- The value '{value}' provided for argument '{argumentName}' m
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/0b376604087c3ee3.
Report an issue: GitHub.