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 != null

View on GitHub (pinned to dbf9771522)

Solutions

  1. 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")).
  2. Do not disable CosmosJsonIdConvention unless you provide your own id-mapped property.
  3. 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

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


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/98d74aa965ff42d4. Report an issue: GitHub.