vitessio/vitess · error
unsupported select expression: %v
Error message
unsupported select expression: %v
What it means
matchColInSelect walks the select expressions of a workflow source query and only supports StarExpr and simple AliasedExpr column references. Any other expression type (subqueries, literals, function calls without alias handling, etc.) hits the default branch and is rejected with this error. It is a deliberate limitation of the query-rewrite-rule generator.
Source
Thrown at go/vt/vtctl/workflow/utils.go:320
case *sqlparser.AliasedExpr:
match := selExpr.As
if match.IsEmpty() {
if colExpr, ok := selExpr.Expr.(*sqlparser.ColName); ok {
match = colExpr.Name
} else {
// Cannot match against a complex expression.
continue
}
}
if match.Equal(col) {
colExpr, ok := selExpr.Expr.(*sqlparser.ColName)
if !ok {
return nil, fmt.Errorf("vindex column cannot be a complex expression: %v", sqlparser.String(selExpr))
}
return colExpr, nil
}
default:
return nil, fmt.Errorf("unsupported select expression: %v", sqlparser.String(selExpr))
}
}
return nil, fmt.Errorf("could not find vindex column %v", sqlparser.String(col))
}
func shouldInclude(table string, excludes []string) bool {
// We filter out internal tables elsewhere when processing SchemaDefinition
// structures built from the GetSchema database related API calls. In this
// case, however, the table list comes from the user via the -tables flag
// so we need to filter out internal table names here in case a user has
// explicitly specified some.
// This could happen if there's some automated tooling that creates the list of
// tables to explicitly specify.
// But given that this should never be done in practice, we ignore the request.
if schema.IsInternalOperationTableName(table) {
return false
}
return !slices.Contains(excludes, table)View on GitHub (pinned to 01a25a7d17)
Solutions
- Replace the unsupported select expression with a plain column or `select <cols> from <table>` list.
- Use `select *` or an explicit column list limited to the columns the workflow needs (including the vindex columns).
- Split complex queries out of the workflow definition; workflows copy tables, they do not run arbitrary queries.
Example fix
// before rule := "select count(*) from t" // error: unsupported select expression: count(*) // after rule := "select col1, col2 from t"
Defensive patterns
Strategy: validation
Validate before calling
// keep workflow select lists to StarExpr or column refs only
re := regexp.MustCompile(`(?i)\b(count|sum|avg|min|max)\s*\(|\(\s*select\b`)
if re.MatchString(rule) {
return fmt.Errorf("workflow select must not contain expressions: %s", rule)
} Type guard
func isSupportedSelectExpr(e sqlparser.SelectExpr) bool {
switch e.(type) {
case *sqlparser.StarExpr:
return true
case *sqlparser.AliasedExpr:
return true
}
return false
} Prevention
- Use simple `select cols from table` lists in MoveTables/Reshard rules.
- Never paste analytical or aggregate queries into workflow definitions.
- Let the workflow tooling generate default rules instead of hand-writing them.
When it happens
Trigger: A workflow (MoveTables/Reshard) filter or rule select contains an unsupported expression type in the select list — e.g. `select count(*) from t`, a scalar subquery, or a bare literal — and generateRule calls matchColInSelect to locate a vindex column there.
Common situations: Copy-pasting analytical SELECT queries into migration/reshard filter rules; auto-generated rules containing aggregates; older configs written for other tools being reused with vitess workflows.
Related errors
- vindex column cannot be a complex expression: %v
- workflow has to be defined for action %s
- invalid on-ddl action: %s
- could not find vindex column %v
- %w in keyspace %s for %s
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/1a9b275f2e81aa80.
Report an issue: GitHub.