dotnet/efcore · error · InvalidOperationException

Navigation ' . ' doesn't point to an embedded entity.

Error message

Navigation '{entityType}.{navigationName}' doesn't point to an embedded entity.

What it means

ObjectArrayAccessExpression's constructor throws when a collection INavigation is being bound as an array access but the navigation's target entity type has no containing property name (GetContainingPropertyName() returns null). Cosmos collection navigations must point to embedded (owned) collections so the provider can express them as a JSON array path.

Solutions

  1. Configure the collection target as owned: modelBuilder.Entity<T>().OwnsMany(x => x.Items).
  2. Verify GetContainingPropertyName() on the target entity type returns a value.
  3. Do not query through the collection if it represents cross-document relationships.

Example fix

// before
modelBuilder.Entity<Order>().HasMany(o => o.Items).WithOne();

// after - items are embedded inside the order document
modelBuilder.Entity<Order>().OwnsMany(o => o.Items);
Defensive patterns

Strategy: validation

Validate before calling

// Validate collection navigations are embedded before they are queried.
foreach (var nav in entityType.GetNavigations().Where(n => n.IsCollection && n.TargetEntityType.GetContainingPropertyName() == null))
{
    throw new InvalidOperationException($"Collection navigation {entityType.DisplayName()}.{nav.Name} is not embedded; configure OwnsMany.");
}

Type guard

static bool IsEmbeddedCollectionNavigation(INavigation n) => n.IsCollection && n.TargetEntityType.GetContainingPropertyName() is not null;

Prevention

When it happens

Trigger: Querying through a collection navigation whose target type was not configured as an owned collection (OwnsMany) in OnModelCreating.

Common situations: Defining a one-to-many relationship between two top-level entities without marking the many-side as owned, then projecting or filtering through the collection.

Related errors


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

Appendix: source

Thrown at src/EFCore.Cosmos/Query/Internal/Expressions/ObjectArrayAccessExpression.cs:40

    ///     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
    ///     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>
    public ObjectArrayAccessExpression(
        Expression @object,
        IPropertyBase structuralProperty,
        StructuralTypeProjectionExpression? innerProjection = null)
    {
        ITypeBase targetType;
        string propertyName;

        switch (structuralProperty)
        {
            case INavigation navigation:
                targetType = navigation.TargetEntityType;
                propertyName = navigation.TargetEntityType.GetContainingPropertyName()
                    ?? throw new InvalidOperationException(
                        CosmosStrings.NavigationPropertyIsNotAnEmbeddedEntity(
                            navigation.DeclaringEntityType.DisplayName(), navigation.Name));
                break;
            case IComplexProperty complexProperty:
                targetType = complexProperty.ComplexType;
                propertyName = complexProperty.GetJsonPropertyName();
                break;
            default:
                throw new UnreachableException($"Unexpected structural property type: {structuralProperty.GetType().FullName}");
        }

        PropertyName = propertyName;
        Type = typeof(IEnumerable<>).MakeGenericType(targetType.ClrType);
        StructuralProperty = structuralProperty;
        Object = @object;
        InnerProjection = innerProjection
            ?? new StructuralTypeProjectionExpression(new ObjectReferenceExpression(targetType, ""), targetType);
    }

View on GitHub (pinned to 3a2006ef56)