{"record":{"id":"0062106895df66b4","repo":"litedb-org/LiteDB","slug":"group-by-already-defined-in-this-query","errorCode":null,"errorMessage":"GROUP BY already defined in this query","messagePattern":"GROUP BY already defined in this query","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"LiteDB/Client/Database/LiteQueryable.cs","lineNumber":195,"sourceCode":"        /// Groups the documents of resultset according to a specified key selector expression (support only one GroupBy)\n        /// </summary>\n        public ILiteQueryable<IGrouping<K, T>> GroupBy<K>(Expression<Func<T, K>> keySelector)\n        {\n            var expression = _mapper.GetExpression(keySelector);\n\n            this.GroupBy(expression);\n\n            _mapper.RegisterGroupingType<K, T>();\n\n            return new LiteQueryable<IGrouping<K, T>>(_engine, _mapper, _collection, _query);\n        }\n\n        /// <summary>\n        /// Groups the documents of resultset according to a specified key selector expression (support only one GroupBy)\n        /// </summary>\n        public ILiteQueryable<T> GroupBy(BsonExpression keySelector)\n        {\n            if (_query.GroupBy != null) throw new ArgumentException(\"GROUP BY already defined in this query\");\n\n            _query.GroupBy = keySelector;\n            return this;\n        }\n\n        #endregion\n\n        #region Having\n\n        /// <summary>\n        /// Filter documents after group by pipe according to predicate expression (requires GroupBy and support only one Having)\n        /// </summary>\n        public ILiteQueryable<T> Having(BsonExpression predicate)\n        {\n            if (_query.Having != null) throw new ArgumentException(\"HAVING already defined in this query\");\n\n            _query.Having = predicate;\n            return this;","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/litedb-org/LiteDB/blob/f906a5f850678719e39a39a006cb66dcae563cfa/LiteDB/Client/Database/LiteQueryable.cs#L177-L213","documentation":"Thrown by LiteQueryable.GroupBy(BsonExpression) when _query.GroupBy is already non-null. A query may have exactly one GROUP BY clause; the method stores the expression in a single field rather than a list, so a second assignment is rejected. The strongly-typed GroupBy<K> overload delegates here after registering the grouping type.","triggerScenarios":"Calling the BsonExpression overload twice: col.Query().GroupBy(\"$.Category\").GroupBy(\"$.Region\"), or chaining after the strongly-typed overload returns an ILiteQueryable<T> that still exposes GroupBy(BsonExpression).","commonSituations":"Trying to group by a composite key by chaining two GroupBy calls (as in some SQL dialects), or refactoring a query builder that appends grouping clauses.","solutions":["Combine multiple grouping fields into a single BsonExpression, e.g. GroupBy(\"$.Category + '|' + $.Region\").","If you need hierarchical grouping, perform a second grouping step on the materialized results client-side.","Build the full group key expression once and pass it to a single GroupBy call."],"exampleFix":"// before\nvar q = col.Query().GroupBy(\"$.Category\").GroupBy(\"$.Region\");\n\n// after\nvar q = col.Query().GroupBy(\"$.Category + '|' + $.Region\");","handlingStrategy":"validation","validationCode":"// Compose a single composite group key before calling GroupBy.\nvar groupExpr = string.Join(\" + '|' + \", keys.Select(k => $\"$.{k}\"));\nq.GroupBy(groupExpr);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never chain GroupBy; merge keys into one expression.","Document that LiteDB supports a single GROUP BY clause per query."],"tags":["query","groupby","argument","linq"],"backgroundTag":null,"analyzedSha":"f906a5f850678719e39a39a006cb66dcae563cfa","analyzedAt":"2026-08-13T21:56:30.148Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}