{"record":{"id":"b5ed895ab334ade8","repo":"vitessio/vitess","slug":"invalid-candidatepromotionrule-v","errorCode":null,"errorMessage":"Invalid CandidatePromotionRule: %v","messagePattern":"Invalid CandidatePromotionRule: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"go/vt/vtctl/reparentutil/promotionrule/promotion_rule.go","lineNumber":65,"sourceCode":"\nfunc (r *CandidatePromotionRule) BetterThan(other CandidatePromotionRule) bool {\n\totherOrder, ok := promotionRuleOrderMap[other]\n\tif !ok {\n\t\treturn false\n\t}\n\treturn promotionRuleOrderMap[*r] < otherOrder\n}\n\n// Parse returns a CandidatePromotionRule by name.\n// It returns an error if there is no known rule by the given name.\nfunc Parse(ruleName string) (CandidatePromotionRule, error) {\n\tswitch ruleName {\n\tcase \"prefer\", \"neutral\", \"prefer_not\", \"must_not\":\n\t\treturn CandidatePromotionRule(ruleName), nil\n\tcase \"must\":\n\t\treturn CandidatePromotionRule(\"\"), fmt.Errorf(\"CandidatePromotionRule: %v not supported yet\", ruleName)\n\tdefault:\n\t\treturn CandidatePromotionRule(\"\"), fmt.Errorf(\"Invalid CandidatePromotionRule: %v\", ruleName)\n\t}\n}\n","sourceCodeStart":47,"sourceCodeEnd":68,"githubUrl":"https://github.com/vitessio/vitess/blob/01a25a7d176f94613b8d59d799f438380a8760e4/go/vt/vtctl/reparentutil/promotionrule/promotion_rule.go#L47-L68","documentation":"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.","triggerScenarios":"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.","commonSituations":"Case-sensitivity mistakes ('Prefer'); typos in tablet labels/tags set via vtctldclient; older tooling writing deprecated rule names; hand-edited tablet labels.","solutions":["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)","Re-run the reparent after fixing the label","If set by automation, fix the automation's allowed-values list and add lowercase normalization"],"exampleFix":"// before\npromotion_rule=Prefer_Not\n// after\npromotion_rule=prefer_not","handlingStrategy":"validation","validationCode":"// Normalize and validate before applying tablet labels\nrule = strings.ToLower(strings.TrimSpace(rule))\nif !slices.Contains([]string{\"prefer\", \"neutral\", \"prefer_not\", \"must_not\"}, rule) {\n\treturn fmt.Errorf(\"invalid CandidatePromotionRule %q\", rule)\n}","typeGuard":"func isValidCandidatePromotionRule(s string) bool {\n\tswitch promotionrule.CandidatePromotionRule(s) {\n\tcase promotionrule.Prefer, promotionrule.Neutral, promotionrule.PreferNot, promotionrule.MustNot:\n\t\treturn true\n\t}\n\treturn false\n}","tryCatchPattern":"if _, err := promotionrule.Parse(rule); err != nil {\n\tif strings.Contains(err.Error(), \"Invalid CandidatePromotionRule\") {\n\t\t// fix the tablet label to one of prefer/neutral/prefer_not/must_not\n\t}\n}","preventionTips":["Keep rule names lowercase everywhere","Whitelist values in any UI/automation that writes tablet labels","Audit tablet labels for typos before PRS/ERS"],"tags":["promotion-rule","reparent","config"],"backgroundTag":"invalid-promotion-rule","analyzedSha":"01a25a7d176f94613b8d59d799f438380a8760e4","analyzedAt":"2026-09-01T17:28:30.605Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}