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), nilView on GitHub (pinned to 01a25a7d17)
Solutions
- Remove or merge duplicate --session-variable flags so each name appears once.
- De-duplicate case-insensitively in whatever code builds the flag list.
- 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
- De-duplicate flags case-insensitively in flag-building code.
- Prefer applying overrides in a map before serializing to flags.
- Test templates that merge defaults with user overrides.
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
- Unknown online DDL strategy: '%v'
- session variable %q is not allowed
- BeforeSchema differs
- AfterSchema differs
- --force-cut-over-after is only valid in 'vitess' strategy. F
AI-assisted analysis of vitessio/vitess@01a25a7d17 (2026-09-01).
Data as JSON: /api/errors/096948d027f66841.
Report an issue: GitHub.