vitessio/vitess · error

unsupported mix of '*' and columns

Error message

unsupported mix of '*' and columns

What it means

buildReplicatorPlan/buildTablePlan parses the filter rule's 'select *' query. A '*' is only supported as the sole select expression (the plan is completed later from stream field info); mixing '*' with named columns is not representable in the replication plan and is rejected.

Source

Thrown at go/vt/vttablet/tabletmanager/vreplication/table_plan_builder.go:242

		buf := sqlparser.NewTrackedBuffer(nil)
		buf.Myprintf("select * from %v where in_keyrange(%v)", sqlparser.NewIdentifierCS(tableName), sqlparser.NewStrLiteral(filter))
		query = buf.String()
	case filter == ExcludeStr:
		return nil, nil
	}
	sel, fromTable, err := analyzeSelectFrom(query, parser)
	if err != nil {
		return nil, planError(err, query)
	}
	sendRule := &binlogdatapb.Rule{
		Match: fromTable,
	}

	if expr, ok := sel.SelectExprs.Exprs[0].(*sqlparser.StarExpr); ok {
		// If it's a "select *", we return a partial plan, and complete
		// it when we get back field info from the stream.
		if len(sel.SelectExprs.Exprs) != 1 {
			return nil, planError(errors.New("unsupported mix of '*' and columns"), sqlparser.String(sel))
		}
		if !expr.TableName.IsEmpty() {
			return nil, planError(errors.New("unsupported qualifier for '*' expression"), sqlparser.String(expr))
		}
		sendRule.Filter = query
		tablePlan := &TablePlan{
			TargetName:       tableName,
			SendRule:         sendRule,
			Lastpk:           lastpk,
			Stats:            stats,
			ConvertCharset:   rule.ConvertCharset,
			ConvertIntToEnum: rule.ConvertIntToEnum,
			CollationEnv:     collationEnv,
			WorkflowConfig:   workflowConfig,
		}

		return tablePlan, nil
	}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Use either plain 'select * from t' or an explicit column list — never both
  2. If you need extra computed columns, list all columns explicitly instead of '*'
  3. Fix the filter rule in the MoveTables/Reshard create command and re-run

Example fix

// before
"filter": "select *, id from t"
// after
"filter": "select * from t"  // or list all columns explicitly
Defensive patterns

Strategy: validation

Validate before calling

stmt, err := parser.Parse(filterQuery)
if sel, ok := stmt.(*sqlparser.Select); ok {
    stars := 0
    for _, e := range sel.SelectExprs.Exprs {
        if _, ok := e.(*sqlparser.StarExpr); ok { stars++ }
    }
    if stars > 0 && len(sel.SelectExprs.Exprs) > 1 {
        return errors.New("filter cannot mix '*' with columns")
    }
}

Prevention

When it happens

Trigger: Creating a vreplication stream (MoveTables/Reshard/filter rule) whose filter query is like 'select *, col from t' or 'select col, * from t'.

Common situations: Hand-written filter rules combining explicit columns with '*'; generated rules edited by hand during MoveTables customization.

Related errors


AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01). Data as JSON: /api/errors/b8fb7ed98f324dfb. Report an issue: GitHub.