vitessio/vitess · error

Invalid CandidatePromotionRule: %v

Error message

Invalid CandidatePromotionRule: %v

What it means

promotionrule.Parse rejects any rule name outside the known set (prefer, neutral, prefer_not, must_not) with 'Invalid CandidatePromotionRule'. This guards candidate selection during reparents from mislabeled tablets.

Source

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

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. Find the tablet with the bad label (vtctldclient GetTablets) and correct its promotion_rule to one of: prefer, neutral, prefer_not, must_not (all lowercase)
  2. Re-run the reparent after fixing the label
  3. If set by automation, fix the automation's allowed-values list and add lowercase normalization

Example fix

// before
promotion_rule=Prefer_Not
// after
promotion_rule=prefer_not
Defensive patterns

Strategy: validation

Validate before calling

// Normalize and validate before applying tablet labels
rule = strings.ToLower(strings.TrimSpace(rule))
if !slices.Contains([]string{"prefer", "neutral", "prefer_not", "must_not"}, rule) {
	return fmt.Errorf("invalid CandidatePromotionRule %q", rule)
}

Type guard

func isValidCandidatePromotionRule(s string) bool {
	switch promotionrule.CandidatePromotionRule(s) {
	case promotionrule.Prefer, promotionrule.Neutral, promotionrule.PreferNot, promotionrule.MustNot:
		return true
	}
	return false
}

Try / catch

if _, err := promotionrule.Parse(rule); err != nil {
	if strings.Contains(err.Error(), "Invalid CandidatePromotionRule") {
		// fix the tablet label to one of prefer/neutral/prefer_not/must_not
	}
}

Prevention

When it happens

Trigger: During PRS/ERS, a tablet record's candidate promotion rule string is anything unrecognized (typo like 'prefered', 'MUST_NOT', empty convention mismatch) and gets passed to promotionrule.Parse.

Common situations: Case-sensitivity mistakes ('Prefer'); typos in tablet labels/tags set via vtctldclient; older tooling writing deprecated rule names; hand-edited tablet labels.

Related errors


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