vitessio/vitess · error
vindex column cannot be a complex expression: %v
Error message
vindex column cannot be a complex expression: %v
What it means
During workflow (Reshard/MigrateTables) setup, generateRule builds query rewrite rules from the source select statement. matchColInSelect matches a vindex column against the select list, and if the matched select item is anything other than a plain column reference (e.g. an expression, function call, or alias of an expression), it cannot be safely rewritten, so this error is thrown. The library requires vindex columns to be simple column references in the select list.
Source
Thrown at go/vt/vtctl/workflow/utils.go:315
func matchColInSelect(col sqlparser.IdentifierCI, sel *sqlparser.Select) (*sqlparser.ColName, error) {
for _, selExpr := range sel.GetColumns() {
switch selExpr := selExpr.(type) {
case *sqlparser.StarExpr:
return &sqlparser.ColName{Name: col}, nil
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.View on GitHub (pinned to 01a25a7d17)
Solutions
- Rewrite the select list so the vindex column is selected as a plain column reference (e.g. `select id from t`, not `select id+1 from t`).
- If a transformed value is needed, compute it downstream or use a generated column in the schema and select that column directly.
- Check your filter rules / -tables specification for expressions and simplify them to bare column names for vindex columns.
Example fix
// before rule := "select id + 1 from t" // error: vindex column cannot be a complex expression: id + 1 // after rule := "select id from t"
Defensive patterns
Strategy: validation
Validate before calling
// ensure vindex columns are plain column refs in your workflow select
for _, sel := range rule.SelectExpressions() {
if _, ok := sqlparser.String(sel); ok && !strings.Contains(sqlparser.String(sel), "(") {
continue
}
return fmt.Errorf("select list must be plain columns: %s", sqlparser.String(sel))
} Type guard
func isPlainColumn(e sqlparser.SelectExpr) bool {
ae, ok := e.(*sqlparser.AliasedExpr)
if !ok { return false }
_, isCol := ae.Expr.(*sqlparser.ColName)
return isCol
} Prevention
- Always select vindex columns as bare column references in workflow filters/rules.
- Validate filter rules with the SQL parser before submitting a workflow.
- Avoid computed/derived columns in migration select lists; use generated columns in the schema instead.
When it happens
Trigger: Running a vexec/MoveTables or Reshard workflow where the source select list (e.g. from a filter rule or -tables spec) selects a vindex column via a complex expression like `select id+1 from t` or `select upper(name) from t` instead of a bare column, and generateRule tries to match that column in the select list.
Common situations: Users hand-writing workflow filter/ON DDL rules with computed columns; migrating tables whose primary vindex is derived (function of columns); copying select clauses from application queries into migration rules.
Related errors
- unsupported select expression: %v
- could not find vindex column %v
- workflow has to be defined for action %s
- invalid on-ddl action: %s
- %w in keyspace %s for %s
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/44e428daecdcc6ee.
Report an issue: GitHub.