vitessio/vitess · error
unsupported distinct expression usage: %v
Error message
unsupported distinct expression usage: %v
What it means
Aggregate functions with DISTINCT (e.g. `COUNT(DISTINCT x)`) are not supported by the vstreamer plan builder because distinct aggregation cannot be streamed incrementally. Only non-distinct aggregates — specifically `COUNT(*)` — are allowed.
Source
Thrown at go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go:492
cexpr.references[as.String()] = true
return cexpr, nil
}
if expr, ok := aliased.Expr.(*sqlparser.FuncExpr); ok {
switch fname := expr.Name.Lowered(); fname {
case "keyspace_id":
if len(expr.Exprs) != 0 {
return nil, fmt.Errorf("unsupported multiple keyspace_id expressions: %v", sqlparser.String(expr))
}
tpb.sendSelect.AddSelectExpr(&sqlparser.AliasedExpr{Expr: aliased.Expr})
// The vstreamer responds with "keyspace_id" as the field name for this request.
cexpr.expr = &sqlparser.ColName{Name: sqlparser.NewIdentifierCI("keyspace_id")}
return cexpr, nil
}
}
if expr, ok := aliased.Expr.(sqlparser.AggrFunc); ok {
if sqlparser.IsDistinct(expr) {
return nil, fmt.Errorf("unsupported distinct expression usage: %v", sqlparser.String(expr))
}
switch fname := expr.AggrName(); fname {
case "count":
if _, ok := expr.(*sqlparser.CountStar); !ok {
return nil, fmt.Errorf("only count(*) is supported: %v", sqlparser.String(expr))
}
cexpr.operation = opCount
return cexpr, nil
case "sum":
if len(expr.GetArgs()) != 1 {
return nil, fmt.Errorf("unsupported multiple columns in sum clause: %v", sqlparser.String(expr))
}
innerCol, ok := expr.GetArg().(*sqlparser.ColName)
if !ok {
return nil, fmt.Errorf("unsupported non-column name in sum clause: %v", sqlparser.String(expr))
}
if !innerCol.Qualifier.IsEmpty() {
return nil, fmt.Errorf("unsupported qualifier for column: %v", sqlparser.String(innerCol))View on GitHub (pinned to 01a25a7d17)
Solutions
- Remove the DISTINCT keyword from the aggregate
- Use plain `COUNT(*)` if counting is the goal — it is the only supported aggregate form
- Perform distinct aggregation outside the replication pipeline, e.g. in a downstream query
Example fix
// before SELECT COUNT(DISTINCT uid) AS c FROM t // after SELECT COUNT(*) AS c FROM t
Defensive patterns
Strategy: validation
Validate before calling
for _, e := range sel.SelectExprs {
ae, ok := e.(*sqlparser.AliasedExpr)
if !ok { continue }
if ag, ok := ae.Expr.(sqlparser.AggrFunc); ok {
if sqlparser.IsDistinct(ag) {
return fmt.Errorf("DISTINCT aggregates unsupported: %v", sqlparser.String(ae))
}
}
} Type guard
func isSupportedAggregate(e sqlparser.Expr) bool {
cs, ok := e.(*sqlparser.CountStar)
return ok && cs != nil
} Try / catch
if err != nil && strings.Contains(err.Error(), "distinct expression") {
return fmt.Errorf("remove DISTINCT from aggregates in filter select list: %w", err)
} Prevention
- Never use DISTINCT inside aggregates in filter rules
- Limit filter aggregates to COUNT(*)
- Move complex aggregation to downstream queries, not replication filters
When it happens
Trigger: A filter select list contains `SUM(DISTINCT col)`, `COUNT(DISTINCT col)`, `AVG(DISTINCT col)`, etc.
Common situations: Porting analytical queries into replication filter rules; users expecting full aggregate support in MoveTables filters.
Related errors
- unsupported from expression (%T)
- unsupported from source (%T)
- primary key column %v is not allowed to reference an aggrega
- unsupported: %v
- value out of range
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/2ba27378e536b3e5.
Report an issue: GitHub.