vitessio/vitess · error

unsupported qualifier for column: %v

Error message

unsupported qualifier for column: %v

What it means

When building a vstreamer table plan, WHERE-clause columns must be unqualified: the plan resolves the column against the single source table via findColumn, so a qualifier (table or alias prefix) is rejected with this error even though it would be valid SQL elsewhere.

Source

Thrown at go/vt/vttablet/tabletserver/vstreamer/planbuilder.go:650

func (plan *Plan) analyzeWhere(vschema *localVSchema, where *sqlparser.Where) error {
	if where == nil {
		return nil
	}
	// Only a series of AND expressions are supported.
	exprs := splitAndExpression(nil, where.Expr)
	for _, expr := range exprs {
		switch expr := expr.(type) {
		case *sqlparser.ComparisonExpr:
			opcode, err := getOpcode(expr)
			if err != nil {
				return err
			}
			qualifiedName, ok := expr.Left.(*sqlparser.ColName)
			if !ok {
				return fmt.Errorf("unexpected: %v", sqlparser.String(expr))
			}
			if !qualifiedName.Qualifier.IsEmpty() {
				return fmt.Errorf("unsupported qualifier for column: %v", sqlparser.String(qualifiedName))
			}
			colnum, err := findColumn(plan.Table, qualifiedName.Name)
			if err != nil {
				return err
			}
			// The Right Expr is typically expected to be a Literal value,
			// except for the IN operator, where a Tuple value is expected.
			// Handle the IN operator case first.
			if opcode == In {
				values, ok := expr.Right.(sqlparser.ValTuple)
				if !ok {
					return fmt.Errorf("unexpected: %v", sqlparser.String(expr))
				}
				err := plan.appendTupleFilter(values, opcode, colnum)
				if err != nil {
					return err
				}
				// Add it to the expressions that get pushed down to mysqld.

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Remove the table/alias qualifier from the column: col = value instead of t.col = value
  2. Keep the filter tied to exactly one table so unqualified names are unambiguous
  3. Re-test the filter after stripping qualifiers; findColumn matches bare names only

Example fix

// before
where t.status = 'active'
// after
where status = 'active'
Defensive patterns

Strategy: validation

Validate before calling

// strip/verify column qualifiers in filter predicates
for _, p := range predicates {
    if cn, ok := p.left.(*sqlparser.ColName); ok && !cn.Qualifier.IsEmpty() {
        return fmt.Errorf("remove qualifier from %v", sqlparser.String(cn))
    }
}

Prevention

When it happens

Trigger: A VStream filter predicate uses a qualified column — e.g. t.col = 5 or ks.t.col = 'x' — while building the plan for a single table, triggering the 'unsupported qualifier' branch in analyzeWhere.

Common situations: Copy-pasted queries that qualify columns with the table alias; filters generated from larger queries where qualification was required; users referencing keyspace-qualified names in filter rules.

Related errors


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