vitessio/vitess · error

duplicate session variable name: %q

Error message

duplicate session variable name: %q

What it means

ValidateSessionVariables rejects case-insensitive duplicate session variable names in the ordered list parsed from repeated --session-variable options. Setting the same variable twice is ambiguous, so the second occurrence fails validation. Comparison is via strings.ToLower normalization.

Source

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

		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)
		}
		seen[normalizedName] = struct{}{}
	}
	return nil
}

// SetStatement returns a SET statement for the variable.
func (variable SessionVariable) SetStatement() (string, error) {
	if err := ValidateSessionVariable(variable); err != nil {
		return "", err
	}
	// A connection default or an earlier assignment may enable
	// NO_BACKSLASH_ESCAPES.
	// In that mode, encoding O'Reilly as 'O\'Reilly' closes the string after
	// the backslash; on a multi-statement DBA connection, a crafted suffix could
	// then be parsed as another statement. A hex literal is parsed safely
	// regardless of the active sql_mode.
	return fmt.Sprintf("set @@session.%s=X'%x'", variable.Name, variable.Value), nil

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Remove or merge duplicate --session-variable flags so each name appears once.
  2. De-duplicate case-insensitively in whatever code builds the flag list.
  3. If override semantics are needed, apply the last value yourself before constructing the strategy string.

Example fix

// before
strategy := "online --session-variable wait_timeout=100 --session-variable wait_timeout=200"
// after
strategy := "online --session-variable wait_timeout=200"
Defensive patterns

Strategy: validation

Validate before calling

seen := map[string]bool{}
for _, v := range vars {
    k := strings.ToLower(v.Name)
    if seen[k] { /* dedupe: keep last */ }
    seen[k] = true
}

Try / catch

if err := schema.ValidateSessionVariables(vars); err != nil {
    return fmt.Errorf("invalid session variables: %w", err)
}

Prevention

When it happens

Trigger: Passing two --session-variable flags with the same name in any case, e.g. --session-variable wait_timeout=100 --session-variable WAIT_TIMEOUT=200, which reaches this error through DDLStrategySetting.SessionVariables().

Common situations: Scripted command builders that append flags without de-duplicating; configuration templates merging user defaults with overrides; shell wrappers accumulating flags across layers.

Related errors


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