vitessio/vitess · warning

invalid session variable name: %q

Error message

invalid session variable name: %q

What it means

ValidateSessionVariable checks that a session variable name parsed from a ddl_strategy-style value is a safe MySQL system-variable identifier before it is interpolated into SQL. If the name does not match sessionVariableNameRegexp, it is rejected to prevent injection of arbitrary SQL through variable names.

Source

Thrown at go/vt/schema/ddl_strategy.go:213

func (setting *DDLStrategySetting) IsSingletonContext() bool {
	return setting.hasFlag(singletonContextFlag)
}

// IsSingletonTable checks if strategy options include --singleton-table
func (setting *DDLStrategySetting) IsSingletonTable() bool {
	return setting.hasFlag(singletonTableFlag)
}

// IsAllowZeroInDateFlag checks if strategy options include --allow-zero-in-date
func (setting *DDLStrategySetting) IsAllowZeroInDateFlag() bool {
	return setting.hasFlag(allowZeroInDateFlag)
}

// ValidateSessionVariable ensures a variable name is safe to interpolate as a
// MySQL system variable identifier.
func ValidateSessionVariable(variable SessionVariable) error {
	if !sessionVariableNameRegexp.MatchString(variable.Name) {
		return fmt.Errorf("invalid session variable name: %q", variable.Name)
	}
	if _, ok := deniedSessionVariables[strings.ToLower(variable.Name)]; ok {
		return fmt.Errorf("session variable %q is not allowed", variable.Name)
	}
	return nil
}

// ValidateSessionVariables validates variable names and rejects
// case-insensitive duplicates.
func ValidateSessionVariables(variables []SessionVariable) error {
	seen := map[string]struct{}{}
	for _, variable := range variables {
		if err := ValidateSessionVariable(variable); err != nil {
			return err
		}
		normalizedName := strings.ToLower(variable.Name)
		if _, ok := seen[normalizedName]; ok {
			return fmt.Errorf("duplicate session variable name: %q", variable.Name)

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Pass only valid MySQL identifier-style variable names (letters, digits, underscore) in the SessionVariable.
  2. Sanitize/trim user-supplied variable strings before constructing SessionVariable values.
  3. Check the denied-session-variables list too — even well-formed names like some privileged variables are rejected by the companion check.
  4. Fix the parser/splitter that produced a name containing '=' or whitespace.

Example fix

// before
v := SessionVariable{Name: "sql_mode; DROP TABLE t", Value: "x"}
ValidateSessionVariable(v) // error
// after
v := SessionVariable{Name: "sql_mode", Value: "STRICT_TRANS_TABLES"}
ValidateSessionVariable(v) // nil
Defensive patterns

Strategy: validation

Validate before calling

var nameRe = regexp.MustCompile(`^[A-Za-z0-9_]+$`)
if !nameRe.MatchString(v.Name) { return fmt.Errorf("unsafe variable name %q", v.Name) }

Type guard

func isSafeVarName(name string) bool {
  for _, r := range name {
    if !(r == '_' || (r >= 'a' && r <= 'z') || (r >= 'A' && r <= 'Z') || (r >= '0' && r <= '9')) { return false }
  }
  return len(name) > 0
}

Try / catch

if err := schema.ValidateSessionVariable(v); err != nil {
  return fmt.Errorf("session variable rejected: %w", err)
}

Prevention

When it happens

Trigger: Calling schema.ValidateSessionVariable (or SetStatement / ValidateSessionVariables) with a SessionVariable whose Name contains illegal characters — spaces, quotes, semicolons, parentheses, or other non-identifier characters.

Common situations: Malformed SET @@ddl_strategy input like 'sql_mode=...; DROP TABLE x' or a name with stray whitespace; app code building session variables from untrusted user input; parsing bugs splitting name=value pairs incorrectly.

Related errors


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