vitessio/vitess · error

invalid flags for %v strategy: %s

Error message

invalid flags for %v strategy: %s

What it means

ParseDDLStrategy collects leftover RuntimeOptions() for the parsed strategy. Strategies vitess, online, mysql, and direct accept no runtime flag options — any unrecognized or unconsumed flags in the ddl_strategy string produce this error listing the offending flags.

Source

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

	if _, err := setting.SessionVariables(); err != nil {
		return nil, err
	}
	cutoverAfter, err := setting.ForceCutOverAfter()
	if err != nil {
		return nil, err
	}
	switch setting.Strategy {
	case DDLStrategyVitess, DDLStrategyOnline:
	default:
		if cutoverAfter != 0 {
			return nil, fmt.Errorf("--force-cut-over-after is only valid in 'vitess' strategy. Found %v value in '%v' strategy", cutoverAfter, setting.Strategy)
		}
	}

	switch setting.Strategy {
	case DDLStrategyVitess, DDLStrategyOnline, DDLStrategyMySQL, DDLStrategyDirect:
		if opts := setting.RuntimeOptions(); len(opts) > 0 {
			return nil, fmt.Errorf("invalid flags for %v strategy: %s", setting.Strategy, strings.Join(opts, " "))
		}
	}

	return setting, nil
}

// isFlag return true when the given string is a CLI flag of the given name
func isFlag(s string, name string) bool {
	if s == "-"+name {
		return true
	}
	if s == "--"+name {
		return true
	}
	return false
}

// hasFlag returns true when Options include named flag

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Remove unknown flags from the ddl_strategy value until only supported ones remain.
  2. Check flag spelling against supported parameters (--force-cut-over-after, --retain-artifacts, --allow-foreign-keys, --post-completion-gradient, etc.).
  3. Update tooling/config that was written for an older Vitess release where the flag existed.
  4. Validate the strategy string with TestParseDDLStrategy-like checks or in a dev environment before production SET statements.

Example fix

// before
SET @@ddl_strategy='vitess --force-cutover-after=24h'; // typo
// after
SET @@ddl_strategy='vitess --force-cut-over-after=24h';
Defensive patterns

Strategy: validation

Validate before calling

setting, err := schema.ParseDDLStrategy(candidate)
if err != nil { return fmt.Errorf("rejecting ddl_strategy %q: %v", candidate, err) }

Type guard

func hasNoUnknownFlags(s *schema.DDLStrategySetting) bool { return len(s.RuntimeOptions()) == 0 }

Try / catch

_, err := schema.ParseDDLStrategy(strategyName)
if err != nil {
  return fmt.Errorf("ddl_strategy flags rejected: %w", err)
}

Prevention

When it happens

Trigger: SET @@ddl_strategy='vitess --unknown-flag=x' or 'mysql --foo=bar' — options remain after parsing known parameters like --force-cut-over-after, --retain-artifacts, --post-completion-gradient, etc.

Common situations: Typos in flag names (--force-cutover-after misspelled); flags from other migration tools (gh-ost options) pasted in; stale flags removed in newer Vitess versions still set by old config; case/space mistakes in parameter names.

Related errors


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