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
- Apply WithPartitionKey immediately on the DbSet before any other LINQ operator.
- Reorder the query so the partition key is the first operator: context.Blogs.WithPartitionKey("A").Where(...).
- 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
- Always call WithPartitionKey immediately on the DbSet, before any other LINQ operator.
- Review query-building helpers to ensure partition key is the first operator.
- Add a unit test asserting WithPartitionKey is applied to a raw DbSet root.
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
- 'WithPartitionKey' can only be called once in a query. See h
- 'WithPartitionKey' only accepts simple constant or parameter
- The partition key value is of type '{valueType}' which is no
- The partition key value supplied for '{propertyType}' proper
- The partition key properties for entity type '{entityType1}'
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/42e94d91f8a2fe21.
Report an issue: GitHub.