dotnet/efcore · error · InvalidOperationException

'WithPartitionKey' only accepts simple constant or parameter

Error message

'WithPartitionKey' only accepts simple constant or parameter arguments. See https://aka.ms/efdocs-cosmos-partition-keys for more information.

What it means

Thrown when an argument passed to WithPartitionKey is not a simple constant or parameter expression. The provider translates partition key values directly into Cosmos SDK PartitionKey construction, which requires concrete values known at execution time; computed expressions, method calls, or member accesses cannot be turned into a partition key without evaluation.

Source

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

        {
            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;
        }

        if (method.DeclaringType == typeof(Queryable) && method.IsGenericMethod)
        {
            switch (methodCallExpression.Method.Name)
            {
                // The following is a bad hack to account for https://github.com/dotnet/efcore/issues/32957#issuecomment-2165864086.
                // Basically for the query form Where(b => b.Posts.GetElementAt(0).Id == 1), nav expansion moves the property access
                // forward, generating Where(b => b.Posts.Select(p => p.Id).GetElementAt(0)); unfortunately that means that GetElementAt()
                // over a bare array in Cosmos doesn't get translated to a simple indexer as it should (b["Posts"][0].Id), since the
                // reordering messes things up.
                case nameof(Queryable.ElementAt) or nameof(Queryable.ElementAtOrDefault)

View on GitHub (pinned to dbf9771522)

Solutions

  1. Extract the value into a local variable or parameter before calling WithPartitionKey: var tenant = config.TenantId; context.Blogs.WithPartitionKey(tenant).
  2. If the value comes from a service, resolve it to a concrete value first and pass that.
  3. Ensure the argument is a literal, a captured constant, or an EF query parameter.

Example fix

// before
var q = context.Blogs.WithPartitionKey(_config.CurrentTenant.Id);
// after
var tenantId = _config.CurrentTenant.Id;
var q = context.Blogs.WithPartitionKey(tenantId);
Defensive patterns

Strategy: validation

Validate before calling

// Extract values into locals/parameters before passing to WithPartitionKey
var tenantId = _config.CurrentTenant.Id;
if (string.IsNullOrEmpty(tenantId)) throw new InvalidOperationException("TenantId required");
var q = context.Blogs.WithPartitionKey(tenantId);

Prevention

When it happens

Trigger: Passing a computed value, a property of another entity, or a method-call result to WithPartitionKey, e.g. WithPartitionKey(someObject.TenantId) where someObject.TenantId is not a captured constant or a query parameter.

Common situations: Reading the partition key from a config object's instance property rather than a captured local or a parameter. Passing an expression that depends on query state.

Related errors


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