dotnet/efcore · error · InvalidOperationException
The mapping strategy
Error message
The mapping strategy '{mappingStrategy}' specified on '{entityType}' is not supported. What it means
Thrown by ValidateMappingStrategy when the mapping strategy string set on an entity type is not one of the recognized values (TPH, TPC, TPT). The switch falls through to the default case, so any unknown/misspelled strategy annotation is rejected at validation time.
Solutions
- Use the fluent API: UseTphMappingStrategy(), UseTptMappingStrategy(), or UseTpcMappingStrategy().
- If setting the annotation directly, use RelationalAnnotationNames.TphMappingStrategy / TpcMappingStrategy / TptMappingStrategy constants, never literals.
- Check for trailing spaces or wrong casing in any custom convention that writes the strategy.
Example fix
// before
modelBuilder.Entity<Order>()
.Metadata.SetAnnotation("Relational:MappingStrategy", "TablePerType"); // unknown -> throws 424
// after
modelBuilder.Entity<Order>().UseTptMappingStrategy(); Defensive patterns
Strategy: validation
Validate before calling
var allowed = new HashSet<string?>
{
null,
RelationalAnnotationNames.TphMappingStrategy,
RelationalAnnotationNames.TptMappingStrategy,
RelationalAnnotationNames.TpcMappingStrategy,
};
foreach (var entityType in modelBuilder.Model.GetEntityTypes())
{
var strategy = (string?)entityType[RelationalAnnotationNames.MappingStrategy];
if (!allowed.Contains(strategy))
throw new InvalidOperationException($"{entityType.DisplayName()} has unknown mapping strategy '{strategy}'.");
} Prevention
- Always use UseTphMappingStrategy()/UseTptMappingStrategy()/UseTpcMappingStrategy() instead of writing the annotation directly.
- If you must write the annotation, reference the RelationalAnnotationNames constants, never literals.
- Add a test that asserts every entity's mapping strategy is one of the three known values.
When it happens
Trigger: Calling SetMappingStrategy with a typo or unsupported value (e.g. "TPTT", "TablePerHierarchy", "tpt" with wrong casing/format), or writing the RelationalAnnotationNames.MappingStrategy annotation directly with an invalid string.
Common situations: Hand-writing the annotation string instead of using UseTptMappingStrategy()/UseTpcMappingStrategy()/UseTphMappingStrategy(); custom conventions that set the annotation; casing/whitespace mistakes; stale code referencing a renamed strategy constant.
Related errors
- The mapping strategy
- Both ' ' and ' ' are mapped to the table ' '. All the…
- Both ' ' and ' ' are mapped to the stored procedure ' '…
- Both ' ' and ' ' are mapped to the view ' '. All the entity…
- The entity type ' ' is not mapped, so by default the owned…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/028c0fdc5338b36c.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:2201
}
}
}
/// <summary>
/// Validates that the given mapping strategy is supported
/// </summary>
/// <param name="entityType">The entity type.</param>
/// <param name="mappingStrategy">The mapping strategy.</param>
protected virtual void ValidateMappingStrategy(IEntityType entityType, string? mappingStrategy)
{
switch (mappingStrategy)
{
case RelationalAnnotationNames.TphMappingStrategy:
case RelationalAnnotationNames.TpcMappingStrategy:
case RelationalAnnotationNames.TptMappingStrategy:
break;
default:
throw new InvalidOperationException(
RelationalStrings.InvalidMappingStrategy(
mappingStrategy, entityType.DisplayName()));
}
}
private static void ValidateNonTphMapping(IEntityType rootEntityType, StoreObjectType storeObjectType)
{
var isTpc = rootEntityType.GetMappingStrategy() == RelationalAnnotationNames.TpcMappingStrategy;
var derivedTypes = new Dictionary<StoreObjectIdentifier, IEntityType>();
foreach (var entityType in rootEntityType.GetDerivedTypesInclusive())
{
var storeObject = StoreObjectIdentifier.Create(entityType, storeObjectType);
if (storeObject == null)
{
var unmappedOwnedType = entityType.GetReferencingForeignKeys()
.Where(fk => fk.IsOwnership)
.Select(fk => fk.DeclaringEntityType)
.FirstOrDefault(owned => StoreObjectIdentifier.Create(owned, storeObjectType) == nullView on GitHub (pinned to 3a2006ef56)