vitessio/vitess · error

could not find vindex column %v

Error message

could not find vindex column %v

What it means

After scanning the entire SELECT list, matchColInSelect could not find any select expression matching the primary vindex column name. generateInserts needs this column to construct per-shard INSERT statements; without it, the copy plan cannot be built.

Source

Thrown at go/vt/wrangler/materializer.go:1497

				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 (mz *materializer) createStreams(ctx context.Context, insertsMap map[string]string) error {
	return mz.forAllTargets(func(target *topo.ShardInfo) error {
		inserts := insertsMap[target.ShardName()]
		targetPrimary, err := mz.wr.ts.GetTablet(ctx, target.PrimaryAlias)
		if err != nil {
			return vterrors.Wrapf(err, "GetTablet(%v) failed", target.PrimaryAlias)
		}
		buf := &strings.Builder{}
		t := template.Must(template.New("").Parse(inserts))
		input := map[string]string{
			"keyrange": key.KeyRangeString(target.KeyRange),
			"dbname":   targetPrimary.DbName(),
		}
		if err := t.Execute(buf, input); err != nil {
			return err
		}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Include the primary vindex column in the SELECT list with the exact target column name
  2. Fix the alias so it matches the target table's vindex column name
  3. Check `vtctldclient GetVSchema <target-keyspace>` to confirm which columns form the primary vindex

Example fix

// before (vindex column id missing)
{"sourceExpression":"select name, email from users"}
// after
{"sourceExpression":"select id, name, email from users"}
Defensive patterns

Strategy: validation

Validate before calling

vs, _ := wr.ts.GetVSchema(ctx, targetKeyspace)
pvCols := vs.Tables[targetTable].ColumnVindexes[0].Columns
sel, _ := parser.Parse(sourceExpr)
for _, c := range pvCols {
    if _, err := findColInSelect(sel.(*sqlparser.Select), c); err != nil {
        return fmt.Errorf("SourceExpression must include primary vindex column %s", c)
    }
}

Prevention

When it happens

Trigger: SourceExpression for a sharded target table omits the primary vindex column from its select list, or aliases it under a different name than the TargetTable's vindex column, e.g. `select id as uid, name from users` where vindex column is `id`.

Common situations: Filters that project only a subset of columns while the table is sharded; column renamed between source and target; typo in column name in the select list.

Related errors


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