dotnet/efcore · error · InvalidOperationException
'WithPartitionKey' can only be called once in a query. See…
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
CosmosQueryableExtensions.WithPartitionKey records partition key values on the QueryCompilationContext. The visitor checks PartitionKeyPropertyValues.Count before processing and, if it is already populated, throws InvalidOperationException — partition key can only be fixed once per query.
Solutions
- Call WithPartitionKey exactly once per query lifecycle.
- Centralize partition key injection in one helper and guard against double-application.
- Build the query from a single root, applying WithPartitionKey at the start, before any further composition.
Example fix
// before
var q = db.Users.WithPartitionKey("tenantA").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> PartitionOnce<T>(IQueryable<T> q, params object[] keys)
where T : class
{
if (q is IQueryable<T> already && already.Provider.GetType().Name.Contains("Cosmos"))
{
// call WithPartitionKey only on a fresh DbSet root; track via a marker extension if needed
}
return q.WithPartitionKey(keys);
} Prevention
- Centralize WithPartitionKey in one repository method.
- Never combine two IQueryables that each applied WithPartitionKey.
- Document the 'once per query' rule in the helper's XML doc.
When it happens
Trigger: Calling .WithPartitionKey(...) twice on the same IQueryable, or composing two queryables each of which already carries a WithPartitionKey call.
Common situations: Reusable query filters that bake in WithPartitionKey being combined with an ad-hoc per-call WithPartitionKey, or multi-tenant helpers that set the partition key and the caller also sets it.
Related errors
- 'WithPartitionKey' can only be called on an entity query…
- '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/19111d9c266cd54a.
Report an issue: GitHub.
Appendix: 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 3a2006ef56)