bytebase/bytebase · error
rule %s requires naming payload
Error message
rule %s requires naming payload
What it means
Naming rules with regex validation (NAMING_TABLE, NAMING_COLUMN, NAMING_COLUMN_AUTO_INCREMENT) carry their configuration in a NamingRulePayload. validateSQLReviewRule rejects such a rule when GetNamingPayload() returns nil, meaning the payload was never attached to the rule.
Source
Thrown at backend/api/v1/review_config_service.go:351
return errors.Errorf("invalid rule engine: ENGINE_UNSPECIFIED is not allowed for rule %q", rule.Type)
}
if err := validateSQLReviewRule(rule); err != nil {
return err
}
}
return nil
}
// validateSQLReviewRule validates a single SQL review rule's payload.
func validateSQLReviewRule(rule *v1pb.SQLReviewRule) error {
ruleType := storepb.SQLReviewRule_Type(rule.Type)
switch ruleType {
// Naming rules with regex validation
case storepb.SQLReviewRule_NAMING_TABLE, storepb.SQLReviewRule_NAMING_COLUMN, storepb.SQLReviewRule_NAMING_COLUMN_AUTO_INCREMENT:
payload := rule.GetNamingPayload()
if payload == nil {
return errors.Errorf("rule %s requires naming payload", ruleType)
}
// At least one of format or maxLength must be set
if payload.Format == "" && payload.MaxLength <= 0 {
return errors.Errorf("naming rule must specify either format or max_length for rule %s", ruleType)
}
// If format is set, validate it compiles
if payload.Format != "" {
if _, err := regexp.Compile(payload.Format); err != nil {
return errors.Wrapf(err, "invalid naming rule format pattern %q for rule %s", payload.Format, ruleType)
}
}
// If maxLength is set, validate it's positive (maxLength == 0 means not set)
if payload.MaxLength < 0 {
return errors.Errorf("naming rule max_length cannot be negative for rule %s, got %d", ruleType, payload.MaxLength)
}
// Naming rules with template token validation
case storepb.SQLReviewRule_NAMING_INDEX_FK, storepb.SQLReviewRule_NAMING_INDEX_IDX, storepb.SQLReviewRule_NAMING_INDEX_UK, storepb.SQLReviewRule_NAMING_INDEX_PK, storepb.SQLReviewRule_TABLE_DROP_NAMING_CONVENTION:View on GitHub (pinned to 1870550677)
Solutions
- Attach a NamingRulePayload (with format and/or maxLength) to the rule's payload oneof
- Omit the rule entirely until its payload is configured
- Verify the JSON/proto payload field name matches the oneof case (namingPayload)
Example fix
// before
{type: "NAMING_TABLE", level: "ERROR", engine: "ENGINE_MYSQL"}
// after
{type: "NAMING_TABLE", level: "ERROR", engine: "ENGINE_MYSQL", namingPayload: {format: "^t_[a-z]+$"}} Defensive patterns
Strategy: validation
Validate before calling
if isRegexNamingRule(rule.Type) && rule.GetNamingPayload() == nil {
return fmt.Errorf("rule %s needs a namingPayload before saving", rule.Type)
} Type guard
func hasNamingPayload(r *v1pb.SQLReviewRule) bool { return r.GetNamingPayload() != nil } Prevention
- Map each rule type to its required payload kind and enforce it in the form layer
- Never send a rule shell without its payload oneof filled
- Add a unit test asserting every naming rule fixture carries a payload
When it happens
Trigger: Creating or updating a review config with one of the three regex naming rules but no payload field set (oneof payload left empty in the request).
Common situations: API consumers that set rule type/level/engine but forget the payload oneof; UIs that create the rule shell before the payload form is filled; migrations copying rules between configs and dropping the payload.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- invalid rule type: TYPE_UNSPECIFIED is not allowed
- invalid rule engine: ENGINE_UNSPECIFIED is not allowed for r
- rule %s requires number payload
- rule %s requires string array payload
- rule %s requires comment convention payload
AI-assisted analysis of bytebase/bytebase@1870550677 (2026-09-06).
Data as JSON: /api/errors/1f1cfd7f308b2608.
Report an issue: GitHub.