dotnet/efcore · error · InvalidOperationException
The entity type ' ' does not have a property mapped to the…
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 when a document-root entity type has a primary key but no property mapped to the Cosmos JSON 'id' property. Cosmos requires every document to have a string 'id' field, so EF Core requires each root entity to expose one (often the PK converted to string, or a shadow id). The validator scans GetProperties() for one whose GetJsonPropertyName() equals the well-known id JSON name and throws if none exists.
Solutions
- Ensure at least one property is mapped to the JSON 'id' name - typically the PK with a string conversion: modelBuilder.Entity<T>().HasKey(...).HasConversion<string>() or rely on the built-in id convention.
- If you want the PK itself to serve as id, configure its JSON property name to 'id' (GetJsonPropertyName) and ensure a string converter.
- Call HasShadowId on the root if you want EF to manage a shadow id property.
- Verify you have not disabled the CosmosJsonIdConvention or removed the id mapping in OnModelCreating.
Example fix
// before
modelBuilder.Entity<Thing>()
.ToContainer("Things")
.HasKey(t => t.Number); // int PK, no string 'id'
// after
modelBuilder.Entity<Thing>()
.ToContainer("Things")
.HasKey(t => t.Number);
modelBuilder.Entity<Thing>().Property(t => t.Number).HasConversion<string>().ToJsonProperty("id"); Defensive patterns
Strategy: validation
Validate before calling
foreach (var et in dbContext.Model.GetEntityTypes().Where(e => e.IsDocumentRoot()))
{
var hasId = et.GetProperties().Any(p => p.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName);
if (!hasId) throw new InvalidOperationException($"{et.DisplayName()} missing 'id' mapping");
} Prevention
- Keep the CosmosJsonIdConvention enabled so an id shadow property is created automatically.
- When customizing the PK, always ensure one property maps to 'id' as a string.
- Add a unit test that builds the model for every root entity.
When it happens
Trigger: Defining an entity with HasPrimaryKey but never mapping a property to 'id' - e.g. configuring an int PK without HasConversion to string and without the conventional id-mapping shim, or removing the default id mapping. Fires during model validation for any document-root entity.
Common situations: Customizing the primary key without ensuring a string 'id' mapping; setting ToProperty("id") incorrectly; turning off conventions that auto-create the id shadow property; new entity type that the conventions did not wire up an id for.
Related errors
- The type of the ' ' property on ' ' is ' '. All 'id'…
- A full-text index is defined for
- A full-text index on
- A partition key is defined on entity type
- A vector index is defined for
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/98d74aa965ff42d4.
Report an issue: GitHub.
Appendix: 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 3a2006ef56)