{"record":{"id":"0f9ecc2b861be04e","repo":"kubernetes/kops","slug":"cannot-parse-rule-q-v","errorCode":null,"errorMessage":"cannot parse rule %q: %v","messagePattern":"cannot parse rule %q: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/awstasks/securitygroup.go","lineNumber":322,"sourceCode":"}\n\nfunc (d *deleteSecurityGroupRule) DeferDeletion() bool {\n\treturn true\n}\n\nfunc (e *SecurityGroup) FindDeletions(c *fi.CloudupContext) ([]fi.CloudupDeletion, error) {\n\tctx := c.Context()\n\tvar removals []fi.CloudupDeletion\n\n\tif len(e.RemoveExtraRules) == 0 {\n\t\treturn nil, nil\n\t}\n\n\tvar rules []RemovalRule\n\tfor _, s := range e.RemoveExtraRules {\n\t\trule, err := ParseRemovalRule(s)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"cannot parse rule %q: %v\", s, err)\n\t\t}\n\t\trules = append(rules, rule)\n\t}\n\n\tsg, err := e.findEc2(c)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tif sg == nil {\n\t\treturn nil, nil\n\t}\n\n\tcloud := awsup.GetCloud(c)\n\n\tfilters := make([]ec2types.Filter, 0)\n\tif e.ID != nil {\n\t\tfilters = append(filters, awsup.NewEC2Filter(\"group-id\", *e.ID))\n\t} else {","sourceCodeStart":304,"sourceCodeEnd":340,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/awstasks/securitygroup.go#L304-L340","documentation":"FindDeletions parses every entry of the SecurityGroup task's removeExtraRules list with ParseRemovalRule before comparing live EC2 rules. This error wraps any parse failure, so a malformed string in removeExtraRules aborts reconciliation of the whole SecurityGroup task. The DSL is intentionally tiny: only `port=N` or `port=N:M` are valid.","triggerScenarios":"removeExtraRules contains a string that ParseRemovalRule rejects: not of the form key=value (zero or >1 '='), key is not \"port\" (e.g. \"protocol=tcp\"), or the port portion is non-numeric (e.g. \"port=ssh\", \"port=80:http\", \"port=80-\").","commonSituations":"Typo in cluster spec removeExtraRules (e.g. \"ports=22\" instead of \"port=22\"); copy-pasted rule syntax from another tool; forgetting the port range uses ':' not '-'; whitespace variants are trimmed so those are fine, but mixed-case \"Port=22\" fails.","solutions":["Fix the rule string in the cluster spec to `port=N` or `port=N:M` (e.g. `kops edit cluster` / instance-group spec), then `kops update cluster --yes`","Validate syntax locally: split on '=' must yield exactly 2 tokens, left token must be exactly \"port\", both ports must parse with strconv.Atoi","Check kops release notes — the DSL is internal and may have changed between versions","Temporarily remove the offending removeExtraRules entry to unblock the apply, fix, then re-add"],"exampleFix":"// before\nremoveExtraRules: [\"port=22,443\", \"protocol=tcp\"]\n// after\nremoveExtraRules: [\"port=22\", \"port=443\"]","handlingStrategy":"validation","validationCode":"func validateRemovalRules(rules []string) error {\n  for _, s := range rules {\n    if _, err := awstasks.ParseRemovalRule(s); err != nil {\n      return fmt.Errorf(\"removeExtraRules entry %q invalid: %v\", s, err)\n    }\n  }\n  return nil\n}\n// or simply run `kops update cluster` (dry-run) which calls FindDeletions and surfaces this before --yes","typeGuard":null,"tryCatchPattern":"if err := update(); err != nil {\n  var re *kopsapi.RunError\n  if errors.As(err, &re) && strings.Contains(err.Error(), \"cannot parse rule\") {\n    fixSpecRuleAndRerun()\n  }\n}","preventionTips":["Only use the documented DSL: port=N or port=N:M","Grep the cluster spec for removeExtraRules after edits and eyeball syntax","Always dry-run (`kops update cluster`) before --yes","Remember the DSL is internal and version-specific — revalidate after kops upgrades"],"tags":["config","security-group","rule-parsing","validation"],"backgroundTag":"invalid-rule-syntax","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}