{"record":{"id":"bf8d4103ae18612d","repo":"bytebase/bytebase","slug":"invalid-template-token-s-for-rule-s","errorCode":null,"errorMessage":"invalid template token %s for rule %s","messagePattern":"invalid template token (.+?) for rule (.+?)","errorType":"validation","errorClass":null,"httpStatus":400,"severity":"error","filePath":"backend/api/v1/review_config_service.go","lineNumber":383,"sourceCode":"\t\t\treturn errors.Errorf(\"naming rule max_length cannot be negative for rule %s, got %d\", ruleType, payload.MaxLength)\n\t\t}\n\n\t// Naming rules with template token validation\n\tcase 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:\n\t\tpayload := rule.GetNamingPayload()\n\t\tif payload == nil {\n\t\t\treturn errors.Errorf(\"rule %s requires naming payload\", ruleType)\n\t\t}\n\t\t// At least one of format or maxLength must be set\n\t\tif payload.Format == \"\" && payload.MaxLength <= 0 {\n\t\t\treturn errors.Errorf(\"naming rule must specify either format or max_length for rule %s\", ruleType)\n\t\t}\n\t\t// If format is set, validate template tokens\n\t\tif payload.Format != \"\" {\n\t\t\ttokens, _ := advisor.ParseTemplateTokens(payload.Format)\n\t\t\tfor _, token := range tokens {\n\t\t\t\tif _, ok := advisor.TemplateNamingTokens[ruleType][token]; !ok {\n\t\t\t\t\treturn errors.Errorf(\"invalid template token %s for rule %s\", token, ruleType)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// If maxLength is set, validate it's positive (maxLength == 0 means not set)\n\t\tif payload.MaxLength < 0 {\n\t\t\treturn errors.Errorf(\"naming rule max_length cannot be negative for rule %s, got %d\", ruleType, payload.MaxLength)\n\t\t}\n\n\t// Number payload rules\n\tcase storepb.SQLReviewRule_STATEMENT_INSERT_ROW_LIMIT,\n\t\tstorepb.SQLReviewRule_STATEMENT_AFFECTED_ROW_LIMIT,\n\t\tstorepb.SQLReviewRule_STATEMENT_WHERE_MAXIMUM_LOGICAL_OPERATOR_COUNT,\n\t\tstorepb.SQLReviewRule_STATEMENT_MAXIMUM_STATEMENTS_IN_TRANSACTION,\n\t\tstorepb.SQLReviewRule_BUILTIN_STATEMENT_MAXIMUM_SQL_SIZE,\n\t\tstorepb.SQLReviewRule_COLUMN_MAXIMUM_CHARACTER_LENGTH,\n\t\tstorepb.SQLReviewRule_COLUMN_MAXIMUM_VARCHAR_LENGTH,\n\t\tstorepb.SQLReviewRule_COLUMN_AUTO_INCREMENT_INITIAL_VALUE,\n\t\tstorepb.SQLReviewRule_INDEX_KEY_NUMBER_LIMIT,","sourceCodeStart":365,"sourceCodeEnd":401,"githubUrl":"https://github.com/bytebase/bytebase/blob/1870550677fe08f0d2a78c07acd27541464eb945/backend/api/v1/review_config_service.go#L365-L401","documentation":"For template naming rules, the Format string is parsed into template tokens (e.g. {table}, {column}) and every token must be one advisor.TemplateNamingTokens allows for that specific rule type. An unknown or not-applicable token aborts validation with this error.","triggerScenarios":"CreateReviewConfig/UpdateReviewConfig with a template naming rule whose format uses a token not defined for that rule, e.g. NAMING_INDEX_PK with format \"pk_{column}\" when {column} is not a valid token for that rule.","commonSituations":"Users guessing at template placeholders; copying a format from one naming rule to another where the token vocabulary differs; typos like {tablename} instead of {table}.","solutions":["Use only tokens listed for the rule type in advisor.TemplateNamingTokens (e.g. {table} for index rules)","Check the advisor package docs/source for the allowed token set per rule","Remove the offending token or switch to a rule type that supports it"],"exampleFix":"// before\n{type: \"NAMING_INDEX_PK\", namingPayload: {format: \"pk_{column}\"}}\n// after\n{type: \"NAMING_INDEX_PK\", namingPayload: {format: \"pk_{table}\"}}","handlingStrategy":"validation","validationCode":"if p := rule.GetNamingPayload(); p != nil && p.Format != \"\" {\n  tokens, _ := advisor.ParseTemplateTokens(p.Format)\n  for _, t := range tokens {\n    if _, ok := advisor.TemplateNamingTokens[storepb.SQLReviewRule_RuleType(rule.Type)][t]; !ok {\n      return fmt.Errorf(\"token %s not allowed for %s\", t, rule.Type)\n    }\n  }\n}","typeGuard":"func tokensAllowed(ruleType storepb.SQLReviewRule_RuleType, format string) bool {\n  tokens, _ := advisor.ParseTemplateTokens(format)\n  for _, t := range tokens {\n    if _, ok := advisor.TemplateNamingTokens[ruleType][t]; !ok { return false }\n  }\n  return true\n}","tryCatchPattern":"err := updateReviewConfig(ctx, req)\nif err != nil && strings.Contains(err.Error(), \"invalid template token\") {\n  // show the allowed token list for the rule type and re-open the template editor\n}","preventionTips":["Offer a token picker in the UI sourced from advisor.TemplateNamingTokens so only valid tokens can be inserted","Reuse formats only between rules with identical token vocabularies","Keep a per-rule-type cheat sheet of tokens near the naming editor"],"tags":["template","validation","sql-review","naming"],"backgroundTag":"invalid-argument-format","analyzedSha":"1870550677fe08f0d2a78c07acd27541464eb945","analyzedAt":"2026-09-06T21:16:13.665Z","contentChangedAt":"2026-09-06T21:16:13.665Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}