vitessio/vitess · error

CandidatePromotionRule: %v not supported yet

Error message

CandidatePromotionRule: %v not supported yet

What it means

promotionrule.Parse maps a string CandidatePromotionRule to its enum value. The rule 'must' is recognized syntactically but explicitly rejected as not yet implemented, with a dedicated message distinguishing it from fully unknown names.

Source

Thrown at go/vt/vtctl/reparentutil/promotionrule/promotion_rule.go:63

	return []CandidatePromotionRule{Must, Prefer, Neutral, PreferNot, MustNot}
}

func (r *CandidatePromotionRule) BetterThan(other CandidatePromotionRule) bool {
	otherOrder, ok := promotionRuleOrderMap[other]
	if !ok {
		return false
	}
	return promotionRuleOrderMap[*r] < otherOrder
}

// Parse returns a CandidatePromotionRule by name.
// It returns an error if there is no known rule by the given name.
func Parse(ruleName string) (CandidatePromotionRule, error) {
	switch ruleName {
	case "prefer", "neutral", "prefer_not", "must_not":
		return CandidatePromotionRule(ruleName), nil
	case "must":
		return CandidatePromotionRule(""), fmt.Errorf("CandidatePromotionRule: %v not supported yet", ruleName)
	default:
		return CandidatePromotionRule(""), fmt.Errorf("Invalid CandidatePromotionRule: %v", ruleName)
	}
}

View on GitHub (pinned to 01a25a7d17)

Solutions

  1. Change the tablet's candidate promotion rule label to a supported value: 'prefer', 'neutral', 'prefer_not', or 'must_not'
  2. If 'must' semantics are needed, use 'prefer' plus explicit PRS to that tablet (PlannedReparentShard --new-primary)
  3. Implement 'must' support in promotionrule.Parse if your fork requires it, or file/track the upstream feature

Example fix

// before
vtctldclient Tablet ... label promotion_rule=must
// after
vtctldclient Tablet ... label promotion_rule=prefer_not  # or prefer/neutral
Defensive patterns

Strategy: validation

Validate before calling

// Validate promotion rule labels before reparent
switch rule := strings.ToLower(label); rule {
case "prefer", "neutral", "prefer_not", "must_not":
	// ok
case "must":
	return fmt.Errorf("'must' is not supported; use 'prefer' plus explicit PRS")
default:
	return fmt.Errorf("invalid promotion rule %q", label)
}

Type guard

func isValidPromotionRule(s string) bool {
	switch s {
	case "prefer", "neutral", "prefer_not", "must_not":
		return true
	}
	return false
}

Try / catch

if _, err := promotionrule.Parse(rule); err != nil {
	if strings.Contains(err.Error(), "not supported yet") {
		// 'must' requested: downgrade to 'prefer' or fail the workflow early
	}
}

Prevention

When it happens

Trigger: A tablet's CandidatePromotionRule field (from tablet tags/labels, e.g. promoted via ERS/PRS candidate selection) is set to 'must' and reparentutil parses it during EmergencyReparentShard or PlannedReparentShard candidate evaluation.

Common situations: Operator tagged a tablet with promotion rule 'must' expecting hard requirement semantics; tooling or automation copied 'must' from other orchestrator conventions; docs/config examples using unsupported value.

Related errors


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