vitessio/vitess · error
unsupported non-column name or alias in group by clause: %v
Error message
unsupported non-column name or alias in group by clause: %v
What it means
GROUP BY in a vreplication table plan may only reference columns by name (a *sqlparser.ColName). Arbitrary expressions, literals, or positional references in GROUP BY are rejected because the builder resolves each group-by item against select-list aliases via findCol.
Source
Thrown at go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go:557
}
// addCol adds the specified column to the send query
// if it's not already present.
func (tpb *tablePlanBuilder) addCol(ident sqlparser.IdentifierCI) {
tpb.sendSelect.AddSelectExpr(&sqlparser.AliasedExpr{
Expr: &sqlparser.ColName{Name: ident},
})
}
func (tpb *tablePlanBuilder) analyzeGroupBy(groupBy *sqlparser.GroupBy) error {
if groupBy == nil {
// If there's no grouping, the it's an insertNormal.
return nil
}
for _, expr := range groupBy.Exprs {
colname, ok := expr.(*sqlparser.ColName)
if !ok {
return fmt.Errorf("unsupported non-column name or alias in group by clause: %v", sqlparser.String(expr))
}
cexpr := tpb.findCol(colname.Name)
if cexpr == nil {
return fmt.Errorf("group by expression does not reference an alias in the select list: %v", sqlparser.String(expr))
}
if cexpr.operation != opExpr {
return fmt.Errorf("group by expression is not allowed to reference an aggregate expression: %v", sqlparser.String(expr))
}
cexpr.isGrouped = true
}
// If all colExprs are grouped, then it's an insertIgnore.
tpb.onInsert = insertIgnore
for _, cExpr := range tpb.colExprs {
if !cExpr.isGrouped {
// If some colExprs are not grouped, then it's an insertOnDup.
tpb.onInsert = insertOnDup
break
}View on GitHub (pinned to 01a25a7d17)
Solutions
- Group only by a column name that also appears (aliased) in the SELECT list.
- Create an aliased select item for the computed value first, then GROUP BY that alias: SELECT UPPER(name) AS uname ... GROUP BY uname.
- Remove numeric positional group-by items and use explicit column names.
Example fix
// before select upper(name) from t group by 1 // after select upper(name) as uname from t group by uname
Defensive patterns
Strategy: validation
Validate before calling
// Require every GROUP BY item to be a plain column name
func validGroupBy(sel *sqlparser.Select) bool {
for _, e := range sel.GroupBy.Exprs {
if _, ok := e.(*sqlparser.ColName); !ok { return false }
}
return true
} Type guard
func isGroupableCol(n sqlparser.SQLNode) bool { _, ok := n.(*sqlparser.ColName); return ok } Prevention
- Never use expressions, literals, or positions in GROUP BY for workflow queries.
- Alias computed select items and group by the alias name.
When it happens
Trigger: Materialize/vreplication SELECT with GROUP BY <expr>, e.g. GROUP BY UPPER(name), GROUP BY 1, or GROUP BY a+b; analyzeGroupBy's type assertion to *sqlparser.ColName fails.
Common situations: Queries copied from engines supporting GROUP BY expressions/positions; users grouping by computed values without aliasing them in the select list.
Related errors
- group by expression does not reference an alias in the selec
- group by expression is not allowed to reference an aggregate
- only count(*) is supported: %v
- unsupported multiple columns in sum clause: %v
- unsupported non-column name in sum clause: %v
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/0fa444a2c5a85d64.
Report an issue: GitHub.