dotnet/efcore · error · InvalidOperationException
' . ' and ' . ' are both mapped to column ' ' in ' ', but…
Error message
'{entityType1}.{property1}' and '{entityType2}.{property2}' are both mapped to column '{columnName}' in '{table}', but are configured to use different provider types ('{type1}' and '{type2}'). What it means
Two properties sharing a column resolve to different provider CLR types, AND at least one of them is part of a key, foreign key, or unique index. For key/FK/unique-index columns the provider type must match exactly because it drives the index definition and join semantics. Non-key shared columns with differing provider types are tolerated (a value converter is allowed there).
Solutions
- Make the ClrType of both key/FK/unique-index properties identical.
- If a value converter is involved, ensure both sides convert to the same provider type.
- Remove the column from key / FK / unique-index duty on one side if the converter types must differ.
- Remap one of the properties to a separate column.
Example fix
// before modelBuilder.Entity<Tenant>().Property(t => t.Id).HasConversion<Guid>(); modelBuilder.Entity<TenantConfig>().Property(c => c.Id).HasConversion<string>(); // shared PK column // after modelBuilder.Entity<Tenant>().Property(t => t.Id).HasConversion<Guid>(); modelBuilder.Entity<TenantConfig>().Property(c => c.Id).HasConversion<Guid>();
Defensive patterns
Strategy: validation
Validate before calling
foreach (var (col, props) in sharedColumnGroups.Where(g => g.Value.Any(p => p.IsKey() || p.IsForeignKey() || (p.IsIndex() && p.GetContainingIndexes().Any(i => i.IsUnique)))))
{
var providerTypes = props.Select(p =>
{
var m = p.FindRelationalMapping() ?? p.GetTypeMapping();
return m.Converter?.ProviderClrType.UnwrapNullableType() ?? m.ClrType;
}).Distinct().ToList();
if (providerTypes.Count > 1)
Console.WriteLine($"Key/FK/unique-index column {col} has conflicting provider types");
} Try / catch
try { _ = db.Model; } catch (InvalidOperationException ex) when (ex.Message.Contains("different provider types")) { // unify the value converter / CLR type of the key or FK column } Prevention
- For shared key/FK columns, ensure both sides use the same CLR type and value converter.
- Avoid mixing converters on identity/key columns.
- Smoke-test the model at startup.
When it happens
Trigger: ValidateCompatible() resolves provider types via typeMapping.Converter?.ProviderClrType ?? ClrType and, when they differ, throws only if any of: property/duplicateProperty.IsKey(), IsForeignKey(), or is part of a unique index. The check intentionally permits converter differences on plain columns.
Common situations: A shared primary key column where one side uses Guid and the other string; an FK column shared between two entities using different value converters; TPT where a discriminator-derived key column has incompatible converter types.
Related errors
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
- ' . ' and ' . ' are both mapped to column ' ' in ' ', but…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/e4675d9919f1fcac.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:1660
previousTypeString,
currentTypeString));
}
var typeMapping = property.GetRelationalTypeMapping();
var duplicateTypeMapping = duplicateProperty.GetRelationalTypeMapping();
var currentProviderType = typeMapping.Converter?.ProviderClrType.UnwrapNullableType()
?? typeMapping.ClrType;
var previousProviderType = duplicateTypeMapping.Converter?.ProviderClrType.UnwrapNullableType()
?? duplicateTypeMapping.ClrType;
if (currentProviderType != previousProviderType
&& (property.IsKey()
|| duplicateProperty.IsKey()
|| property.IsForeignKey()
|| duplicateProperty.IsForeignKey()
|| (property.IsIndex() && property.GetContainingIndexes().Any(i => i.IsUnique))
|| (duplicateProperty.IsIndex() && duplicateProperty.GetContainingIndexes().Any(i => i.IsUnique))))
{
throw new InvalidOperationException(
RelationalStrings.DuplicateColumnNameProviderTypeMismatch(
duplicateProperty.DeclaringType.DisplayName(),
duplicateProperty.Name,
property.DeclaringType.DisplayName(),
property.Name,
columnName,
storeObject.DisplayName(),
previousProviderType.ShortDisplayName(),
currentProviderType.ShortDisplayName()));
}
var currentComputedColumnSql = property.GetComputedColumnSql(storeObject) ?? "";
var previousComputedColumnSql = duplicateProperty.GetComputedColumnSql(storeObject) ?? "";
if (!currentComputedColumnSql.Equals(previousComputedColumnSql, StringComparison.OrdinalIgnoreCase))
{
throw new InvalidOperationException(
RelationalStrings.DuplicateColumnNameComputedSqlMismatch(
duplicateProperty.DeclaringType.DisplayName(),View on GitHub (pinned to 3a2006ef56)