dotnet/efcore · error · InvalidOperationException

The LINQ expression '{expression}' could not be translated.

Error message

The LINQ expression '{expression}' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.

What it means

The InMemory query provider's projection binding visitor fell back to index-based (client-evaluation) binding and encountered a ProjectionBindingExpression whose server projection resolves to a nested InMemoryQueryExpression (a subquery). Subqueries cannot be lifted into the client projection list as a scalar, so translation aborts. This is EF's generic 'could not be translated' error surfaced because the InMemory provider has limited query-translation capability compared to relational providers.

Source

Thrown at src/EFCore.InMemory/Query/Internal/InMemoryProjectionBindingExpressionVisitor.cs:117

            {
                switch (expression)
                {
                    case ConstantExpression:
                        return expression;

                    case ProjectionBindingExpression projectionBindingExpression:
                        var mappedProjection = _queryExpression.GetProjection(projectionBindingExpression);
                        if (mappedProjection is EntityProjectionExpression entityProjection)
                        {
                            return AddClientProjection(entityProjection, typeof(ValueBuffer));
                        }

                        if (mappedProjection is not InMemoryQueryExpression)
                        {
                            return AddClientProjection(mappedProjection, expression.Type.MakeNullable());
                        }

                        throw new InvalidOperationException(CoreStrings.TranslationFailed(projectionBindingExpression.Print()));

                    case MaterializeCollectionNavigationExpression materializeCollectionNavigationExpression:
                    {
                        var subquery = _queryableMethodTranslatingExpressionVisitor.TranslateSubquery(
                            materializeCollectionNavigationExpression.Subquery)!;
                        _clientProjections!.Add(subquery.QueryExpression);
                        return new CollectionResultShaperExpression(
                            new ProjectionBindingExpression(
                                _queryExpression, _clientProjections.Count - 1, typeof(IEnumerable<ValueBuffer>)),
                            subquery.ShaperExpression,
                            materializeCollectionNavigationExpression.Navigation,
                            materializeCollectionNavigationExpression.Navigation.ClrType.GetSequenceType());
                    }

                    case MethodCallExpression methodCallExpression:
                        if (methodCallExpression.Method.IsGenericMethod
                            && methodCallExpression.Method.DeclaringType == typeof(Enumerable)
                            && methodCallExpression.Method.Name == nameof(Enumerable.ToList)

View on GitHub (pinned to dbf9771522)

Solutions

  1. Insert AsEnumerable()/ToList() before the Select that contains the subquery so the projection runs client-side.
  2. Rewrite the projection to avoid nested subqueries; fetch aggregates in a separate query and join client-side.
  3. Simplify the projection to only mapped scalar/entity properties the InMemory provider can translate.

Example fix

// before
var q = db.Blogs
    .Select(b => new { b, Count = db.Posts.Count(p => p.BlogId == b.Id) });
// after
var q = db.Blogs.AsEnumerable()
    .Select(b => new { b, Count = db.Posts.Count(p => p.BlogId == b.Id) });
Defensive patterns

Strategy: try-catch

Try / catch

try
{
    foreach (var item in query) { /* ... */ }
}
catch (InvalidOperationException ex) when (ex.Message.Contains("could not be translated"))
{
    // fall back to client evaluation
    foreach (var item in query.AsEnumerable()) { /* ... */ }
}

Prevention

When it happens

Trigger: A LINQ query against an InMemory DbSet whose final projection contains a correlated subquery (e.g. an aggregate or scalar sub-select inside Select) that the InMemory translator cannot fold into the server query. The first server-side translation pass already failed, so the visitor retries with index-based binding and still cannot handle the nested query expression.

Common situations: Queries that run fine on SQL Server/SQLite but fail on the InMemory provider (e.g. in unit tests) because the projection contains subqueries, custom functions, or operators the InMemory translator does not understand. Common when projecting related aggregates like 'new { Blog = b, LatestPost = b.Posts.OrderByDescending(p => p.Id).FirstOrDefault() }'.

Related errors


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