{"record":{"id":"ef08ec546c1b0172","repo":"dotnet/efcore","slug":"the-linq-expression-expression-could-not-be-tr-ef08ec","errorCode":null,"errorMessage":"The LINQ expression '{expression}' could not be translated. Additional information: {details} 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.","messagePattern":"The LINQ expression '(.+?)' could not be translated\\. Additional information: (.+?) 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\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPreprocessor.cs","lineNumber":42,"sourceCode":"        QueryCompilationContext queryCompilationContext)\n        : base(dependencies, queryCompilationContext)\n    {\n    }\n\n    /// <summary>\n    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to\n    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in\n    ///     any release. You should only use it directly in your code with extreme caution and knowing that\n    ///     doing so can result in application failures when updating to a new Entity Framework Core release.\n    /// </summary>\n    public override Expression Process(Expression query)\n    {\n        var result = base.Process(query);\n\n        return result is MethodCallExpression { Method.IsGenericMethod: true } methodCallExpression\n            && (methodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.GroupByWithKeySelector\n                || methodCallExpression.Method.GetGenericMethodDefinition() == QueryableMethods.GroupByWithKeyElementSelector)\n                ? throw new InvalidOperationException(\n                    CoreStrings.TranslationFailedWithDetails(methodCallExpression.Print(), InMemoryStrings.NonComposedGroupByNotSupported))\n                : result;\n    }\n\n    /// <inheritdoc />\n    protected override bool IsEfConstantSupported\n        => true;\n}\n","sourceCodeStart":24,"sourceCodeEnd":51,"githubUrl":"https://github.com/dotnet/efcore/blob/3a2006ef569de08368d59db5e1468aa8f407e4f8/src/EFCore.InMemory/Query/Internal/InMemoryQueryTranslationPreprocessor.cs#L24-L51","documentation":"The InMemory query translation preprocessor overrides Process and inspects the top-level expression tree after base preprocessing. If the result is a MethodCallExpression whose generic method definition is Queryable.GroupByWithKeySelector or Queryable.GroupByWithKeyElementSelector (i.e. a GroupBy that has NOT been composed into a further aggregation or projection), it throws TranslationFailedWithDetails with the detail message NonComposedGroupByNotSupported. The InMemory provider only supports GroupBy that is immediately followed by a server-translatable aggregate; a standalone GroupBy yielding IGrouping sequences is not supported.","triggerScenarios":"Writing a query like ctx.Blogs.GroupBy(b => b.Author) or ctx.Blogs.GroupBy(b => b.Author, b => b.Title) where the GroupBy result (IGrouping) is consumed directly without a following aggregate (Sum, Count, Select of aggregate). The throw happens at preprocessing time before the query reaches the translator.","commonSituations":"Porting queries from EF Core SQL providers (which support GroupBy yielding groups in some versions) to InMemory tests, or writing grouping logic that assumes the provider can stream IGrouping sequences. Developers who iterate over Group By results with nested loops hit this.","solutions":["Compose the GroupBy into an aggregate immediately: .GroupBy(...).Select(g => new { Key = g.Key, Count = g.Count() }).","Insert AsEnumerable() before GroupBy to perform grouping entirely on the client side.","If you need the raw groups, materialize with ToList() first then use LINQ-to-Objects GroupBy."],"exampleFix":"// before — non-composed GroupBy producing IGrouping\nvar groups = ctx.Blogs.GroupBy(b => b.Author);\nforeach (var g in groups) { /* iterate groups */ }\n\n// after — compose into aggregate projection\nvar groups = ctx.Blogs\n    .GroupBy(b => b.Author)\n    .Select(g => new { Author = g.Key, Count = g.Count() });\n\n// or — client-side grouping\nvar groups = ctx.Blogs.AsEnumerable().GroupBy(b => b.Author);","handlingStrategy":"validation","validationCode":"// Validate: ensure every GroupBy is immediately followed by a server-translatable\n// aggregate or projection. If raw IGrouping sequences are needed, use AsEnumerable.\n// Check: is the GroupBy result composed into Select(g => ...) with aggregates?\n// Safe pattern:\nvar result = ctx.Blogs\n    .GroupBy(b => b.Author)\n    .Select(g => new { Author = g.Key, Count = g.Count() });","typeGuard":null,"tryCatchPattern":"try\n{\n    return query.ToList();\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"GroupBy\"))\n{\n    // Switch to client-side grouping\n    return query.AsEnumerable().GroupBy(keySelector).ToList();\n}","preventionTips":["Always compose GroupBy into an aggregate (Count, Sum, Select of aggregate).","If raw IGrouping sequences are needed, materialize with AsEnumerable() first.","Avoid iterating GroupBy results directly from an IQueryable.","Test GroupBy queries against the InMemory provider in integration tests."],"tags":["efcore","inmemory","query-translation","groupby","client-eval"],"backgroundTag":null,"analyzedSha":"3a2006ef569de08368d59db5e1468aa8f407e4f8","analyzedAt":"2026-08-11T23:42:04.146Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}