vitessio/vitess · warning

error getting select: %s

Error message

error getting select: %s

What it means

After parsing the synthetic tenant query ('select * from t where <col> = <lit>'), getTenantClause asserts the AST node is a *sqlparser.Select. A successfully parsed statement that is not a Select indicates the constructed SQL was not a plain SELECT (unexpected, given the fixed template), so the function bails with this error, reporting the tenant id value in the message.

Source

Thrown at go/vt/vtctl/workflow/utils.go:873

	case querypb.Type_INT64:
		_, err := strconv.Atoi(vrOptions.TenantId)
		if err != nil {
			return nil, fmt.Errorf("tenant id is not a valid int: %s", vrOptions.TenantId)
		}
		tenantId = vrOptions.TenantId
	case querypb.Type_VARCHAR:
		tenantId = sqltypes.EncodeStringSQL(vrOptions.TenantId)
	default:
		return nil, fmt.Errorf("unsupported tenant column type: %s", tenantColumnType)
	}

	stmt, err := parser.Parse(fmt.Sprintf("select * from t where %s = %s", sqlescape.EscapeID(tenantColumnName), tenantId))
	if err != nil {
		return nil, err
	}
	sel, ok := stmt.(*sqlparser.Select)
	if !ok {
		return nil, fmt.Errorf("error getting select: %s", tenantId)
	}
	return &sel.Where.Expr, nil
}

func changeKeyspaceRouting(ctx context.Context, ts *topo.Server, tabletTypes []topodatapb.TabletType,
	sourceKeyspace, targetKeyspace, reason string,
) error {
	routes := make(map[string]string)
	for _, tabletType := range tabletTypes {
		suffix := getTabletTypeSuffix(tabletType)
		routes[sourceKeyspace+suffix] = targetKeyspace
	}
	if err := updateKeyspaceRoutingRules(ctx, ts, reason, routes); err != nil {
		return err
	}
	return ts.RebuildSrvVSchema(ctx, nil)
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Verify the tenant column name is a plain identifier; quote with backticks if it contains special characters (sqlescape.EscapeID handles this).
  2. Retry with a simple alphanumeric tenant column name to isolate the problem.
  3. If reproducible, file a Vitess bug with the tenant column name/type and tenant id used.
  4. Check the wrapped parser error (returned first) for the root cause of the unexpected parse.

Example fix

// before
tenant_column: "select *" // odd column name confuses generated SQL
// after
--tenant-column tenant_id
Defensive patterns

Strategy: try-catch

Try / catch

expr, err := getTenantClause(...)
if err != nil {
	if strings.Contains(err.Error(), "error getting select") {
		log.Errorf("tenant clause builder produced non-SELECT AST (tenantId=%v): %v", tenantID, err)
	}
	return err
}

Prevention

When it happens

Trigger: Practically only when the parsed statement is something other than a Select — e.g. the generated WHERE text leads the parser to produce a non-Select AST (set/other statement) — an internal invariant failure in the tenant clause builder.

Common situations: Rarely seen in the field; would surface as an internal error while building tenant-filtered MoveTables streams, typically after unusual tenant column names or values edge their way into the generated SQL.

Related errors


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