dotnet/efcore · error · InvalidOperationException
'DefaultIfEmpty' cannot be applied after a client-evaluated
Error message
'DefaultIfEmpty' cannot be applied after a client-evaluated projection. Consider applying 'DefaultIfEmpty' before last 'Select' or use 'AsEnumerable' before 'DefaultIfEmpty' to apply it on client-side.
What it means
ApplyDefaultIfEmpty throws when _clientProjections.Count != 0 (InMemoryQueryExpression.cs:461-463). DefaultIfEmpty needs the server-side structure intact to synthesise the empty/default row; after a client-evaluated projection that structure is gone.
Source
Thrown at src/EFCore.InMemory/Query/Internal/InMemoryQueryExpression.cs:463
{
throw new InvalidOperationException(InMemoryStrings.SetOperationsNotAllowedAfterClientEvaluation);
}
ServerQueryExpression = Call(
setOperationMethodInfo.MakeGenericMethod(typeof(ValueBuffer)), ServerQueryExpression, source2.ServerQueryExpression);
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual void ApplyDefaultIfEmpty()
{
if (_clientProjections.Count != 0)
{
throw new InvalidOperationException(InMemoryStrings.DefaultIfEmptyAppliedAfterProjection);
}
ServerQueryExpression = Call(
EnumerableMethods.DefaultIfEmptyWithArgument.MakeGenericMethod(typeof(ValueBuffer)),
ServerQueryExpression,
Constant(new ValueBuffer(Enumerable.Repeat((object?)null, _projectionMappingExpressions.Count).ToArray())));
ReplaceProjection(
_projectionMapping.ToDictionary(
kv => kv.Key,
kv => kv.Value switch
{
EntityProjectionExpression p => MakeEntityProjectionNullable(p),
var p when !p.Type.IsNullableType()
=> Coalesce(
MakeReadValueNullable(p),
p.Type.GetDefaultValueConstant()),View on GitHub (pinned to dbf9771522)
Solutions
- Move DefaultIfEmpty before the last Select so it operates on server-evaluated data.
- Use AsEnumerable() before DefaultIfEmpty to apply it client-side.
- Replace manual DefaultIfEmpty with a navigation or GroupJoin which EF can translate.
Example fix
// before var q = db.Blogs.Select(b => new Dto(b)).DefaultIfEmpty(); // after var q = db.Blogs.DefaultIfEmpty().Select(b => b == null ? null : new Dto(b));
Defensive patterns
Strategy: try-catch
Try / catch
try
{
var r = query.Select(proj).DefaultIfEmpty().ToList();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("DefaultIfEmpty"))
{
var r = query.AsEnumerable().Select(proj).DefaultIfEmpty().ToList();
} Prevention
- Call DefaultIfEmpty before the last Select, or use AsEnumerable() before it.
- Prefer navigations/GroupJoin for left-join semantics over manual DefaultIfEmpty.
When it happens
Trigger: Calling DefaultIfEmpty() after a Select that causes client evaluation, e.g. db.Blogs.Select(b => new Dto(b)).DefaultIfEmpty().
Common situations: Manually implementing left-join semantics with Select(...).DefaultIfEmpty(), or applying DefaultIfEmpty on a projected collection. Often appears when translating hand-written SQL left joins to LINQ.
Related errors
- The LINQ expression '{expression}' could not be translated.
- Unable to translate set operation after client projection ha
- Using 'Distinct' operation on a projection containing a subq
- The LINQ expression '{expression}' could not be translated.
- This enumerator cannot be reset.
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/215f3a2302602e8e.
Report an issue: GitHub.