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

Generic EF Core translation-failure message (no detail list) thrown when a LINQ expression — typically a TVF/db-function argument — could not be translated to SQL and TranslationErrorDetails is null. The user is told to rewrite the query or explicitly switch to client evaluation.

Solutions

  1. Identify the printed expression in the error and simplify it (remove client-side method calls, computed members).
  2. Insert AsEnumerable()/ToList() before the unsupported operator to force client evaluation of that portion.
  3. Check that the DB function / TVF is registered and its arguments are mapped properties or literals.
  4. If a provider translation is missing, file an issue or upgrade the provider.

Example fix

// before
var q = ctx.Customers.FromSqlInterpolated($"SELECT * FROM dbo.GetCustomers({someExpr()})");
// after — evaluate the argument client-side
var arg = someExpr();
var q = ctx.Customers.FromSqlInterpolated($"SELECT * FROM dbo.GetCustomers({arg})");
Defensive patterns

Strategy: fallback

Try / catch

try { var r = await query.ToListAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("could not be translated"))
{
    logger.LogWarning("Translation failed; falling back to client eval: {Msg}", ex.Message);
    var r = await query.AsEnumerable().ToListAsync(); // already materialized
}

Prevention

When it happens

Trigger: Calling a table-valued function or DB function whose argument (or the function itself) the relational translator cannot render as SQL, with no per-element error details collected. The source region is the TVF-argument translation loop's throw.

Common situations: Using an unmapped custom method inside a query, a TVF with an unsupported argument expression, mixing client-side methods into a server-side query, or hitting a provider translation gap.

Related errors


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

Appendix: source

Thrown at src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.cs:140

                    {
                        string call;
                        var methodInfo = function.DbFunctions.Last().MethodInfo;
                        if (methodInfo != null)
                        {
                            var methodCall = Expression.Call(
                                // Declaring types would be derived db context.
                                Expression.Default(methodInfo.DeclaringType!),
                                methodInfo,
                                tableValuedFunctionQueryRootExpression.Arguments);

                            call = methodCall.Print();
                        }
                        else
                        {
                            call = $"{function.DbFunctions.Last().Name}()";
                        }

                        throw new InvalidOperationException(
                            TranslationErrorDetails == null
                                ? CoreStrings.TranslationFailed(call)
                                : CoreStrings.TranslationFailedWithDetails(call, TranslationErrorDetails));
                    }

                    arguments.Add(sqlArgument);
                }

                var entityType = tableValuedFunctionQueryRootExpression.EntityType;
                var alias = _sqlAliasManager.GenerateTableAlias(function);
                var translation = new TableValuedFunctionExpression(alias, function, arguments);
                var queryExpression = CreateSelect(entityType, translation);

                return CreateShapedQueryExpression(entityType, queryExpression);
            }

            case EntityQueryRootExpression entityQueryRootExpression
                when entityQueryRootExpression.GetType() == typeof(EntityQueryRootExpression)

View on GitHub (pinned to 3a2006ef56)