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

Every Cosmos document root entity type must have a property that maps to the JSON 'id' field (Cosmos requires it as the document's primary key). During serializer construction, if no property on a document-root entity resolves to the JSON name 'id', the provider throws NoIdProperty. The Cosmos convention normally creates this property, so hitting the error means the convention was suppressed or a custom configuration removed it.

Solutions

  1. Add a property and ensure its JSON name is 'id' (e.g. .ToJsonProperty("id") or let the default convention create one).
  2. Do not disable/replace CosmosJsonIdConvention unless you also configure an explicit 'id' property.
  3. If you renamed the Id CLR property, map it back: .Property(x => x.Key).ToJsonProperty("id").

Example fix

// before
modelBuilder.Entity<Order>()
    .Property(o => o.Key)
    .ToJsonProperty("identifier"); // no 'id' property -> throws

// after
modelBuilder.Entity<Order>()
    .Property(o => o.Key)
    .ToJsonProperty("id");
Defensive patterns

Strategy: validation

Validate before calling

// Validate every document-root entity has an 'id'-mapped property
foreach (var et in dbContext.Model.GetEntityTypes().Where(t => t.IsDocumentRoot()))
{
    var hasId = et.GetProperties().Any(p => p.GetJsonPropertyName() == "id");
    if (!hasId) throw new InvalidOperationException($"{et.DisplayName()} has no 'id' property.");
}

Try / catch

try { await dbContext.Database.EnsureCreatedAsync(ct); }
catch (InvalidOperationException ex) when (ex.Message.Contains("mapped to 'id'"))
{
    // add/repair an 'id'-mapped property, then retry.
}

Prevention

When it happens

Trigger: A document-root entity type (IsDocumentRoot() true) where no property's GetJsonPropertyName() equals 'id'. Usually because the user explicitly removed the id property, changed its JSON name, or disabled the Cosmos id convention. See CosmosStructuralTypeSerializer.cs:84-87.

Common situations: Overriding the JSON name of the id property (e.g. ToJsonProperty("identifier")) without providing another 'id'-mapped property. Removing conventions including CosmosJsonIdConvention. Renaming the Id property and breaking the convention mapping.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/806f27eb8003891b. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Cosmos/Storage/Internal/CosmosStructuralTypeSerializer.cs:84

        _ordinalKeyProperty = structuralType.GetProperties().SingleOrDefault(p => p.IsOrdinalKeyProperty());
        _scalarProperties =
        [
            .. structuralType.GetProperties().Where(p => p.IsPersisted() && p != _discriminatorProperty?.Property).Select(p
                => (p, p.GetJsonPropertyName(),
                    p.GetJsonValueReaderWriter()
                    ?? p.GetTypeMapping().JsonValueReaderWriter
                    ?? throw new UnreachableException("Property without JsonValueReaderWriter")))
        ];
        _complexProperties =
            [.. structuralType.GetComplexProperties().Select(cp => (cp, cp.GetJsonPropertyName(), provider.Get(cp.ComplexType)))];

        if (structuralType is IEntityType entityType)
        {
            if (entityType.IsDocumentRoot())
            {
                _jsonIdProperty = structuralType.GetProperties()
                        .FirstOrDefault(p => p.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName)
                    ?? throw new InvalidOperationException(CosmosStrings.NoIdProperty(structuralType.DisplayName()));
                _container = entityType.GetContainer()
                    ?? throw new UnreachableException("Document root entity type does not have container.");
            }

            _navigations =
            [
                .. entityType.GetNavigations().Where(n => n.ForeignKey.IsOwnership && !n.IsOnDependent).Select(n
                    => (n,
                        n.TargetEntityType.GetContainingPropertyName()
                        ?? throw new UnreachableException("Owned entity without containing property name"),
                        provider.Get(n.TargetEntityType)))
            ];
        }
    }

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in

View on GitHub (pinned to 3a2006ef56)