vitessio/vitess · error

tenant id is not a valid int: %s

Error message

tenant id is not a valid int: %s

What it means

getTenantClause builds a WHERE clause for tenant-filtered queries during multi-tenant MoveTables. If the tenant column is typed INT64, the TenantId from VReplicationOptions must parse as an integer; strconv.Atoi failure triggers this error. It prevents generating an invalid SQL literal (e.g. an unquoted string in an integer comparison).

Source

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

) (*sqlparser.Expr, error) {
	if vrOptions.TenantId == "" {
		return nil, nil
	}
	if targetVSchema == nil || targetVSchema.MultiTenantSpec == nil {
		return nil, errors.New("target keyspace not defined, or it does not have multi-tenant spec")
	}
	tenantColumnName := targetVSchema.MultiTenantSpec.TenantIdColumnName
	tenantColumnType := targetVSchema.MultiTenantSpec.TenantIdColumnType
	if tenantColumnName == "" {
		return nil, errors.New("tenant column name not defined in multi-tenant spec")
	}

	var tenantId string
	switch tenantColumnType {
	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
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Pass a plain integer tenant id (e.g. 42) matching the tenant column's INT64 type.
  2. Strip whitespace, quotes, or extra characters from the tenant id argument.
  3. If tenant ids are genuinely non-numeric, the tenant column should be VARCHAR — verify the column type and use the appropriate value.

Example fix

// before
--source-tenant-id "acme-corp" // tenant column is INT64
// after
--source-tenant-id 42
Defensive patterns

Strategy: validation

Validate before calling

if tenantColumnType == querypb.Type_INT64 {
	if _, err := strconv.Atoi(strings.TrimSpace(tenantID)); err != nil {
		return fmt.Errorf("tenant id %q must be an integer for INT64 tenant column", tenantID)
	}
}

Type guard

func isValidIntTenantID(v string) bool { _, err := strconv.Atoi(strings.TrimSpace(v)); return err == nil }

Try / catch

clause, err := getTenantClause(...)
if err != nil {
	if strings.Contains(err.Error(), "tenant id is not a valid int") {
		return fmt.Errorf("fix --source-tenant-id: must be a plain integer for this column: %w", err)
	}
	return err
}

Prevention

When it happens

Trigger: Running MoveTables with --source-tenant-id (or equivalent VReplicationOptions.TenantId) whose value is non-numeric while the tenant column in the table is an integer type (INT64).

Common situations: Tenant IDs stored as integers but operator passed an alphanumeric identifier (e.g. 'TENANT-42'); leading/trailing spaces or a comma-separated list passed instead of one integer; copy-paste from config where tenant keys are strings.

Related errors


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