dotnet/efcore · error · InvalidOperationException

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

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

WithPartitionKey must sit directly on an EntityQueryRootExpression (a DbSet or entity query root). If Arguments[0] is not an EntityQueryRootExpression (for example, it follows a Where/Select/Join that rewrites the root) the visitor throws InvalidOperationException with WithPartitionKeyBadNode.

Solutions

  1. Place .WithPartitionKey(k) immediately after the DbSet, before any other LINQ operator.
  2. If using a global query filter, set the partition key at query creation time on the raw DbSet.
  3. Avoid wrapping the root in another IQueryable extension that returns a non-EntityQueryRootExpression node.

Example fix

// before
var q = db.Users.Where(u => u.Active).WithPartitionKey("tenantA");
// after
var q = db.Users.WithPartitionKey("tenantA").Where(u => u.Active);
Defensive patterns

Strategy: validation

Validate before calling

static IQueryable<T> RootedPartition<T>(DbSet<T> set, object key)
    where T : class
    => set.WithPartitionKey(key);  // call on DbSet root only

Prevention

When it happens

Trigger: Calling .Where(...).WithPartitionKey(k) or .Select(...).WithPartitionKey(k) — i.e. placing WithPartitionKey after operators that change the query root, instead of immediately on the DbSet.

Common situations: Applying WithPartitionKey inside a composed extension after a filter, or wrapping the DbSet in a helper that projects before adding the partition key.

Related errors


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

Appendix: 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 3a2006ef56)