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
- Place .WithPartitionKey(k) immediately after the DbSet, before any other LINQ operator.
- If using a global query filter, set the partition key at query creation time on the raw DbSet.
- 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
- Always apply WithPartitionKey as the first operator on a DbSet.
- Code-review composition helpers that wrap IQueryable to ensure the partition call sits on the root.
- Static-analyze for WithPartitionKey not preceded directly by a DbSet access.
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
- 'WithPartitionKey' can only be called once in a query. See…
- 'WithPartitionKey' only accepts simple constant or…
- A FromSqlExpression has an invalid arguments expression type
- A partition key is defined on entity type
- Bind property on structural type coming out of scalar…
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)