dotnet/efcore · error · InvalidOperationException
Entity type ' ' doesn't contain a property mapped to the…
Error message
Entity type '{entityType}' doesn't contain a property mapped to the store-generated concurrency token column '{missingColumn}' which is used by another entity type sharing the table '{table}'. Add a store-generated property to '{entityType}' which is mapped to the same column; it may be in shadow state. What it means
Thrown during shared-table column validation when entity types share a table and one of them declares a store-generated concurrency token (e.g. rowversion/xmin), but another entity type sharing that same table has no property mapped to that concurrency-token column. EF requires every type sharing the table to observe the token so optimistic-concurrency checks stay consistent across the shared row.
Solutions
- Add a shadow or explicit concurrency-token property on the entity type named in the message, mapped to the same column (e.g. .Property<byte[]>("RowVersion").IsRowToken().HasColumnName(<column>)).
- Remove the concurrency token from the other entity if all partners do not need it.
- Stop table-sharing (map the dependent to its own table) so the token only lives on the principal.
Example fix
// before
modelBuilder.Entity<Order>().ToTable("Orders");
modelBuilder.Entity<OrderDetails>().ToTable("Orders");
modelBuilder.Entity<Order>().Property<byte[]>("RowVersion").IsRowToken();
// OrderDetails has no RowVersion -> error
// after - add a shadow concurrency token mapped to the same column
modelBuilder.Entity<OrderDetails>()
.Property<byte[]>("RowVersion")
.IsRowToken()
.HasColumnName("RowVersion"); Defensive patterns
Strategy: validation
Validate before calling
// Detect table-split types missing the shared concurrency token column before validation.
var tokenProps = sharedTypes.SelectMany(t => t.GetProperties())
.Where(p => p.IsConcurrencyToken()).Select(p => p.GetColumnName(storeObject)).ToHashSet();
foreach (var t in sharedTypes)
{
var myTokenCols = t.GetProperties().Where(p => p.IsConcurrencyToken()).Select(p => p.GetColumnName(storeObject)).ToHashSet();
foreach (var missing in tokenProps.Except(myTokenCols))
Console.WriteLine($"{t.Name} missing concurrency column {missing}");
} Try / catch
try { _ = db.Model; } catch (InvalidOperationException ex) when (ex.Message.Contains("doesn't contain a property mapped to the store-generated concurrency token column")) { // add the shadow token property in OnModelCreating } Prevention
- When adding IsRowToken()/IsConcurrencyToken() to a principal, audit every entity type that shares its table.
- Prefer exposing the concurrency token as a shadow property on all split partners.
- Add a startup model-build smoke test to surface sharing errors before runtime.
When it happens
Trigger: Table splitting (owned types or one-to-one PK sharing) where the principal has IsRowToken()/IsConcurrencyToken() but the dependent sharing the table has no matching property. TableSharingConcurrencyTokenConvention.IsConcurrencyTokenMissing returns true for that entity, the column is added to missingConcurrencyTokens, and the validator throws.
Common situations: Adding a [Timestamp]/byte[] RowVersion to a principal entity that is table-split with an owned/detail entity; switching a column to a concurrency token after the split was configured; using PostgreSQL xmin without exposing it on all split partners.
Related errors
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
- Both entity type ' ' and ' ' were configured to use ' '…
- Current value parameter
- Entity type ' ' has a split mapping, but it doesn't map any…
- Entity type ' ' has a split mapping for ' ', but it also…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/87568747cece950e.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:1455
if (missingConcurrencyTokens != null)
{
missingConcurrencyTokens.Clear();
foreach (var (concurrencyColumn, concurrencyProperties) in concurrencyColumns!)
{
if (TableSharingConcurrencyTokenConvention.IsConcurrencyTokenMissing(concurrencyProperties, entityType, mappedTypes))
{
missingConcurrencyTokens.Add(concurrencyColumn);
}
}
}
ValidateCompatible(entityType, storeObject, propertyMappings, missingConcurrencyTokens, logger);
if (missingConcurrencyTokens != null)
{
foreach (var concurrencyColumn in missingConcurrencyTokens)
{
throw new InvalidOperationException(
RelationalStrings.MissingConcurrencyColumn(
entityType.DisplayName(), concurrencyColumn, storeObject.DisplayName()));
}
}
}
var columnOrders = new Dictionary<int, List<string>>();
foreach (var property in propertyMappings.Values)
{
var columnOrder = property.GetColumnOrder(storeObject);
if (!columnOrder.HasValue)
{
continue;
}
var columns = columnOrders.GetOrAddNew(columnOrder.Value);
columns.Add(property.GetColumnName(storeObject)!);
}View on GitHub (pinned to 3a2006ef56)