vitessio/vitess · error
VT03005
VT03005
Error message
VT03005: cannot group on '%s'
What it means
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.
Source
Thrown at go/vt/vtgate/planbuilder/operators/queryprojection.go:711
for _, selectExpr := range qp.SelectExprs {
getExpr, err := selectExpr.GetExpr()
if err != nil {
continue
}
if ctx.SemTable.EqualsExprWithDeps(getExpr, expr) {
return
}
}
qp.SelectExprs = append(qp.SelectExprs, SelectExpr{
Col: aeWrap(expr),
Aggr: ctx.ContainsAggr(expr),
})
}
func checkForInvalidGroupingExpressions(ctx *plancontext.PlanningContext, expr sqlparser.Expr) {
_ = sqlparser.Walk(func(node sqlparser.SQLNode) (bool, error) {
if ctx.IsAggr(node) {
panic(vterrors.VT03005(sqlparser.String(expr)))
}
_, isSubQ := node.(*sqlparser.Subquery)
arg, isArg := node.(*sqlparser.Argument)
if isSubQ || (isArg && strings.HasPrefix(arg.Name, "__sq")) {
panic(vterrors.VT12001("subqueries in GROUP BY"))
}
return true, nil
}, expr)
}
func SortGrouping(a []GroupBy) {
sort.Slice(a, func(i, j int) bool {
return CompareRefInt(a[i].InnerIndex, a[j].InnerIndex)
})
}
// CompareRefInt compares two references of integers.
// In case either one is nil, it is considered to be smallerView on GitHub (pinned to 01a25a7d17)
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.
Example fix
// before SELECT dept, COUNT(*) FROM emp GROUP BY COUNT(*); // after SELECT dept, COUNT(*) FROM emp GROUP BY dept HAVING COUNT(*) > 1;
Defensive patterns
Strategy: validation
Validate before calling
// Reject aggregates inside GROUP BY before sending the query
_ = sqlparser.Walk(func(n sqlparser.SQLNode) (bool, error) {
if isAggregateFunc(n) && insideGroupBy(n) {
return false, errors.New("GROUP BY cannot contain aggregate functions")
}
return true, nil
}, stmt) Try / catch
if strings.Contains(err.Error(), "VT03005") { /* surface SQL rewrite guidance to caller */ } Prevention
- Review ORM-generated GROUP BY clauses
- Use HAVING for aggregate filtering, not GROUP BY
- Group only on plain columns or non-aggregate expressions
When it happens
Trigger: GROUP BY clause expression whose tree contains any aggregate node (e.g. `GROUP BY COUNT(x)`, or `GROUP BY SUM(a)+b`).
Common situations: 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(*)`.
Related errors
- group by expression is not allowed to reference an aggregate
- unsupported function: %v
- VT12001
- VT13001
- cell mode should be handled by the gateway, not the balancer
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/4bd04e486a6e4078.
Report an issue: GitHub.