dotnet/efcore · error · InvalidOperationException

'WithPartitionKey' can only be called on an entity query roo

Error message

'WithPartitionKey' can only be called on an entity query root. See https://aka.ms/efdocs-cosmos-partition-keys for more information.

What it means

Thrown when WithPartitionKey is applied to a queryable that is not a direct entity query root (the first argument of the WithPartitionKey MethodCallExpression is not an EntityQueryRootExpression). The provider needs a raw DbSet root to inject partition-key filtering; applying it after LINQ operators (Where, Select, Join) destroys the root it can attach to.

Source

Thrown at src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs:175

        return base.Translate(expression);
    }

    /// <inheritdoc />
    protected override Expression VisitMethodCall(MethodCallExpression methodCallExpression)
    {
        var method = methodCallExpression.Method;

        if (methodCallExpression.Method.DeclaringType == typeof(CosmosQueryableExtensions)
            && methodCallExpression.Method.Name == nameof(CosmosQueryableExtensions.WithPartitionKey))
        {
            if (_queryCompilationContext.PartitionKeyPropertyValues.Count > 0)
            {
                throw new InvalidOperationException(CosmosStrings.WithPartitionKeyAlreadyCalled);
            }

            if (methodCallExpression.Arguments[0] is not EntityQueryRootExpression)
            {
                throw new InvalidOperationException(CosmosStrings.WithPartitionKeyBadNode);
            }

            var innerQueryable = Visit(methodCallExpression.Arguments[0]);

            for (var i = 1; i < methodCallExpression.Arguments.Count; i++)
            {
                var value = _sqlTranslator.Translate(methodCallExpression.Arguments[i], applyDefaultTypeMapping: false);
                if (value is not SqlConstantExpression and not SqlParameterExpression)
                {
                    throw new InvalidOperationException(CosmosStrings.WithPartitionKeyNotConstantOrParameter);
                }

                _queryCompilationContext.PartitionKeyPropertyValues.Add(value);
            }

            return innerQueryable;
        }

View on GitHub (pinned to dbf9771522)

Solutions

  1. Apply WithPartitionKey immediately on the DbSet before any other LINQ operator.
  2. Reorder the query so the partition key is the first operator: context.Blogs.WithPartitionKey("A").Where(...).
  3. Ensure the queryable passed to WithPartitionKey is the DbSet itself, not a derived query.

Example fix

// before
var q = context.Blogs.Where(b => b.Active).WithPartitionKey("tenantA");
// after
var q = context.Blogs.WithPartitionKey("tenantA").Where(b => b.Active);
Defensive patterns

Strategy: validation

Validate before calling

// Apply WithPartitionKey directly on the DbSet before composing
IQueryable<Blog> q = context.Blogs.WithPartitionKey(tenantId);
q = q.Where(b => b.Active);

Prevention

When it happens

Trigger: Calling WithPartitionKey after other LINQ operators: context.Blogs.Where(...).WithPartitionKey("A"). Also when composing WithPartitionKey onto a projected or already-transformed queryable.

Common situations: Building a query with filters then appending partition key at the end. Reusable extension methods that apply WithPartitionKey late in the chain.

Related errors


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