dotnet/efcore · error · InvalidOperationException

Navigation '{entityType}.{navigationName}' doesn't point to

Error message

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

What it means

ObjectAccessExpression reads a JSON object embedded in a Cosmos document (used for owned entities and complex properties accessed via a navigation). When constructed with an INavigation whose target entity type has no 'containing property name' (i.e. the navigation is NOT mapped as embedded JSON), it throws InvalidOperationException. Cosmos supports only navigations that are embedded in the same document.

Source

Thrown at src/EFCore.Cosmos/Query/Internal/Expressions/ObjectAccessExpression.cs:38

    /// <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
    ///     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 ObjectAccessExpression(
        Expression @object,
        IPropertyBase structuralProperty)
    {
        ITypeBase structuralType;
        string propertyName;

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

        PropertyName = propertyName;
        StructuralProperty = structuralProperty;
        Object = @object;
        StructuralType = structuralType;
    }

    /// <summary>

View on GitHub (pinned to dbf9771522)

Solutions

  1. Configure the target entity as owned in the same document: builder.Entity<Root>().OwnsOne(r => r.Embedded).
  2. If it must be a separate aggregate, do not navigate to it inside a Cosmos-translated query; load it via a separate query.
  3. For complex values, use a complex property (OwnsOne complex type) instead of an entity navigation.

Example fix

// before
modelBuilder.Entity<Order>().HasOne(o => o.Customer)
    .WithMany().HasForeignKey(o => o.CustomerId);
var q = ctx.Orders.Where(o => o.Customer.Name == "x"); // throws

// after: embed as owned
modelBuilder.Entity<Order>().OwnsOne(o => o.Customer);
Defensive patterns

Strategy: validation

Validate before calling

// Verify a navigation is embedded before querying it.
static bool IsEmbedded(INavigation n)
    => n.TargetEntityType.GetContainingPropertyName() is not null;
var nav = cosmosModel.FindEntityType(typeof(Order))!.FindNavigation(nameof(Order.Customer))!;
if (!IsEmbedded(nav)) throw new InvalidOperationException("Configure Customer as owned.");

Type guard

static bool NavigationIsEmbedded(IEntityType owner, string navName)
    => owner.FindNavigation(navName)?.TargetEntityType.GetContainingPropertyName() is not null;

Try / catch

try { var q = ctx.Orders.Where(o => o.Customer.Name == "x").ToList(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("doesn't point to an embedded entity"))
{ /* reconfigure as OwnsOne or load client-side */ }

Prevention

When it happens

Trigger: Querying (filtering/projecting/navigating) a navigation that is not configured as owned (OwnsOne/OwnsMany) or as a complex type, since Cosmos has no server-side join for non-embedded relationships.

Common situations: Porting a relational model to Cosmos where relationships are modeled as plain foreign keys; forgetting OwnsOne; adding a navigation and querying it before configuring embedding.

Related errors


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