dotnet/efcore · error · InvalidOperationException

'WithPartitionKey' can only be called once in a query. See h

Error message

'WithPartitionKey' can only be called once in a query. See https://aka.ms/efdocs-cosmos-partition-keys for more information.

What it means

Thrown when WithPartitionKey is invoked more than once in the same Cosmos query. The provider records partition key values into a single per-query list on the compilation context and disallows a second call, because combining multiple partition-key filters is not meaningful for a single Cosmos query and would produce ambiguous semantics.

Source

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

                        translatedResponseContinuationTokenLimitInKb,
                        typeof(CosmosPage<>).MakeGenericType(shapedQuery.ShaperExpression.Type)))
                .UpdateResultCardinality(ResultCardinality.Single);
        }

        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);

View on GitHub (pinned to dbf9771522)

Solutions

  1. Call WithPartitionKey exactly once per query, combining the relevant partition key values into a single call if multiple are supported.
  2. Refactor shared query-building helpers so partition key is applied at the outermost composition point only.
  3. If you need to switch partition keys, build a fresh queryable from the DbSet.

Example fix

// before
var q = context.Blogs.WithPartitionKey("tenantA").WithPartitionKey("region1");
// after
var q = context.Blogs.WithPartitionKey("tenantA", "region1");
Defensive patterns

Strategy: validation

Validate before calling

// Centralize partition key application and guard double-call
if (partitionKeyApplied) throw new InvalidOperationException("Partition key already set");
partitionKeyApplied = true;
var q = dbSet.WithPartitionKey(tenantId);

Prevention

When it happens

Trigger: Chaining two WithPartitionKey calls on the same queryable, e.g. context.Blogs.WithPartitionKey("A").WithPartitionKey("B"). Also via composing queryables where each already applies a partition key.

Common situations: Helper methods that each add a partition key, accidentally composed. Migrating from a multi-key relational filter pattern to Cosmos partition keys.

Related errors


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