{"record":{"id":"4bd04e486a6e4078","repo":"vitessio/vitess","slug":"vt03005","errorCode":"VT03005","errorMessage":"VT03005: cannot group on '%s'","messagePattern":"VT03005: cannot group on '(.+?)'","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtgate/planbuilder/operators/queryprojection.go","lineNumber":711,"sourceCode":"\tfor _, selectExpr := range qp.SelectExprs {\n\t\tgetExpr, err := selectExpr.GetExpr()\n\t\tif err != nil {\n\t\t\tcontinue\n\t\t}\n\t\tif ctx.SemTable.EqualsExprWithDeps(getExpr, expr) {\n\t\t\treturn\n\t\t}\n\t}\n\tqp.SelectExprs = append(qp.SelectExprs, SelectExpr{\n\t\tCol:  aeWrap(expr),\n\t\tAggr: ctx.ContainsAggr(expr),\n\t})\n}\n\nfunc checkForInvalidGroupingExpressions(ctx *plancontext.PlanningContext, expr sqlparser.Expr) {\n\t_ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) {\n\t\tif ctx.IsAggr(node) {\n\t\t\tpanic(vterrors.VT03005(sqlparser.String(expr)))\n\t\t}\n\t\t_, isSubQ := node.(*sqlparser.Subquery)\n\t\targ, isArg := node.(*sqlparser.Argument)\n\t\tif isSubQ || (isArg && strings.HasPrefix(arg.Name, \"__sq\")) {\n\t\t\tpanic(vterrors.VT12001(\"subqueries in GROUP BY\"))\n\t\t}\n\t\treturn true, nil\n\t}, expr)\n}\n\nfunc SortGrouping(a []GroupBy) {\n\tsort.Slice(a, func(i, j int) bool {\n\t\treturn CompareRefInt(a[i].InnerIndex, a[j].InnerIndex)\n\t})\n}\n\n// CompareRefInt compares two references of integers.\n// In case either one is nil, it is considered to be smaller","sourceCodeStart":693,"sourceCodeEnd":729,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtgate/planbuilder/operators/queryprojection.go#L693-L729","documentation":"VT03005 is raised by checkForInvalidGroupingExpressions when a GROUP BY expression contains an aggregate function (detected via ctx.IsAggr during the SQLNode walk). Grouping by an aggregate is semantically invalid in SQL — you cannot group on a value computed by aggregation of the same rows.","triggerScenarios":"GROUP BY clause expression whose tree contains any aggregate node (e.g. `GROUP BY COUNT(x)`, or `GROUP BY SUM(a)+b`).","commonSituations":"Typos or misunderstandings of GROUP BY semantics, often from ORM-generated SQL or queries translated from other dialects; e.g. `SELECT dept, COUNT(*) FROM emp GROUP BY COUNT(*)`.","solutions":["Remove the aggregate from GROUP BY; group on the underlying column instead (e.g. `GROUP BY dept`).","If you meant to filter on an aggregate, move it to HAVING (e.g. `HAVING COUNT(*) > 1`).","Fix the ORM/query builder so it emits valid GROUP BY expressions."],"exampleFix":"// before\nSELECT dept, COUNT(*) FROM emp GROUP BY COUNT(*);\n// after\nSELECT dept, COUNT(*) FROM emp GROUP BY dept HAVING COUNT(*) > 1;","handlingStrategy":"validation","validationCode":"// Reject aggregates inside GROUP BY before sending the query\n_ = sqlparser.Walk(func(n sqlparser.SQLNode) (bool, error) {\n    if isAggregateFunc(n) && insideGroupBy(n) {\n        return false, errors.New(\"GROUP BY cannot contain aggregate functions\")\n    }\n    return true, nil\n}, stmt)","typeGuard":null,"tryCatchPattern":"if strings.Contains(err.Error(), \"VT03005\") { /* surface SQL rewrite guidance to caller */ }","preventionTips":["Review ORM-generated GROUP BY clauses","Use HAVING for aggregate filtering, not GROUP BY","Group only on plain columns or non-aggregate expressions"],"tags":["vtgate","group-by","aggregation","unsupported-sql"],"backgroundTag":"invalid-group-by","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}