dotnet/efcore · error · InvalidOperationException

The LINQ expression ' ' could not be translated. Either…

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 InMemoryProjectionBindingExpressionVisitor maps each ProjectionBindingExpression to a server-side projection slot. When the mapped projection is neither an EntityProjectionExpression nor an InMemoryQueryExpression, the visitor cannot produce a shaper for it and throws TranslationFailed. This indicates a projection element that has no server-side representation in the InMemory provider.

Solutions

  1. Identify the expression fragment named in the error message and rewrite the Select to use only translatable constructs (mapped properties, arithmetic, supported methods).
  2. Insert AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync() before the Select to force that projection to run client-side.
  3. If the projection wraps a collection navigation, ensure it is shaped as a subquery rather than a raw method call.
  4. Simplify the Select to the minimal shape and add complexity incrementally to isolate the un-translatable fragment.

Example fix

// before — Reverse has no server translation in InMemory
var result = ctx.Blogs
    .Select(b => new { b.Title, Tags = b.Tags.Reverse().ToList() });

// after — materialize first, then project client-side
var result = ctx.Blogs
    .AsEnumerable()
    .Select(b => new { b.Title, Tags = b.Tags.Reverse().ToList() });
Defensive patterns

Strategy: try-catch

Validate before calling

// There is no pre-flight API to detect un-translatable projections.
// Strategy: isolate complex projections and test them; fall back to client eval.
// Use a try/catch around query execution and retry with AsEnumerable if translation fails.
IQueryable<T> SafeQuery<T>(IQueryable<T> q) => q; // placeholder — real guard is structural review

Try / catch

try
{
    return await query.ToListAsync(cancellationToken);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("could not be translated"))
{
    // Fall back: materialize server-side, then apply the problematic projection client-side
    logger.LogWarning("Server translation failed; switching to client evaluation.");
    var serverData = baseQuery.AsEnumerable();
    return clientProjection(serverData).ToList();
}

Prevention

When it happens

Trigger: A LINQ Select whose projection contains an expression the InMemory provider cannot translate — e.g. calling a custom method, using a property that is not mapped, or embedding a non-translatable sub-expression in the projected shape. The throw happens at query-compilation time when the projection binding visitor walks the Select tree.

Common situations: Calling a CLR method inside Select that has no EF translation (e.g. .Select(x => MyHelper(x.Name))), projecting a computed expression involving unsupported constructs, or upgrading EF Core and hitting a previously-tolerated client-eval path that is now strict.

Related errors


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

Appendix: 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 3a2006ef56)