dotnet/efcore · error · InvalidOperationException
The entity type '{entityType}' does not have a property mapp
Error message
The entity type '{entityType}' does not have a property mapped to the 'id' property in the database. Add a property mapped to 'id'. What it means
Thrown by ValidateKeys for a document-root entity type that has a primary key but no property whose JSON name resolves to "id" (CosmosJsonIdConvention.IdPropertyJsonName). Every Cosmos document requires an "id" property; the CosmosJsonIdConvention normally maps the PK to "id" automatically, so this fires only when that convention was disabled or overridden such that no property lands on the id JSON name.
Source
Thrown at src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs:437
/// 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>
protected virtual void ValidateKeys(
IEntityType entityType,
IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
{
var primaryKey = entityType.FindPrimaryKey();
if (primaryKey == null
|| !entityType.IsDocumentRoot())
{
return;
}
var idProperty = entityType.GetProperties()
.FirstOrDefault(p => p.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName);
if (idProperty == null)
{
throw new InvalidOperationException(CosmosStrings.NoIdProperty(entityType.DisplayName()));
}
var idType = idProperty.GetTypeMapping().Converter?.ProviderClrType
?? idProperty.ClrType;
if (idType != typeof(string))
{
throw new InvalidOperationException(
CosmosStrings.IdNonStringStoreType(idProperty.Name, entityType.DisplayName(), idType.ShortDisplayName()));
}
var partitionKeyPropertyNames = entityType.GetPartitionKeyPropertyNames();
if (partitionKeyPropertyNames.Count == 0)
{
logger.NoPartitionKeyDefined(entityType);
}
else
{
if (entityType.BaseType != nullView on GitHub (pinned to dbf9771522)
Solutions
- Ensure exactly one property on the root entity is mapped to the JSON name "id", typically the single string primary key (modelBuilder.Entity<E>().Property(e => e.Id).ToJsonProperty("id")).
- Do not disable CosmosJsonIdConvention unless you provide your own id-mapped property.
- If the PK is not a single string, allow the convention to generate the "__id"/"id" shadow property.
Example fix
// before
modelBuilder.Entity<User>()
.Property(u => u.Id)
.ToJsonProperty("myId"); // nothing mapped to "id"
// after
modelBuilder.Entity<User>()
.Property(u => u.Id)
.ToJsonProperty("id"); Defensive patterns
Strategy: validation
Validate before calling
using var ctx = new MyContext();
foreach (var e in ctx.Model.GetEntityTypes().Where(t => t.FindPrimaryKey() != null && t.IsDocumentRoot()))
{
var idProp = e.GetProperties().FirstOrDefault(p => p.GetJsonPropertyName() == "id");
Debug.Assert(idProp is not null, $"{e.Name} has no property mapped to the JSON 'id'");
} Try / catch
try { ctx.Model.GetModel(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("does not have a property mapped to the 'id'"))
{
logger.LogError(ex, "Entity is missing a property mapped to Cosmos JSON 'id'");
throw;
} Prevention
- Keep a single string primary key and let the Cosmos convention map it to 'id'.
- Do not disable CosmosJsonIdConvention without providing an explicit id-mapped property.
- Test that every document-root entity has a property with JSON name 'id'.
When it happens
Trigger: Explicitly renaming the primary key's JSON property away from "id" via ToJsonProperty("myId") on a single-property string PK, or removing the id-mapped shadow property, on a root entity type.
Common situations: Custom id conventions that conflict with the built-in one; disabling CosmosJsonIdConvention; mapping a composite/non-string PK and then also suppressing the auto-generated id shadow property.
Related errors
- The type of the '{idProperty}' property on '{entityType}' is
- The time to live for analytical store was configured to '{tt
- The default time to live was configured to '{ttl1}' on '{ent
- The provisioned throughput was configured to '{throughput1}'
- The provisioned throughput was configured as manual on '{man
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/98d74aa965ff42d4.
Report an issue: GitHub.