kubernetes/kops · error
cannot parse rule %q: %v
Error message
cannot parse rule %q: %v
What it means
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.
Source
Thrown at upup/pkg/fi/cloudup/awstasks/securitygroup.go:322
}
func (d *deleteSecurityGroupRule) DeferDeletion() bool {
return true
}
func (e *SecurityGroup) FindDeletions(c *fi.CloudupContext) ([]fi.CloudupDeletion, error) {
ctx := c.Context()
var removals []fi.CloudupDeletion
if len(e.RemoveExtraRules) == 0 {
return nil, nil
}
var rules []RemovalRule
for _, s := range e.RemoveExtraRules {
rule, err := ParseRemovalRule(s)
if err != nil {
return nil, fmt.Errorf("cannot parse rule %q: %v", s, err)
}
rules = append(rules, rule)
}
sg, err := e.findEc2(c)
if err != nil {
return nil, err
}
if sg == nil {
return nil, nil
}
cloud := awsup.GetCloud(c)
filters := make([]ec2types.Filter, 0)
if e.ID != nil {
filters = append(filters, awsup.NewEC2Filter("group-id", *e.ID))
} else {View on GitHub (pinned to 4c8573c808)
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
Example fix
// before removeExtraRules: ["port=22,443", "protocol=tcp"] // after removeExtraRules: ["port=22", "port=443"]
Defensive patterns
Strategy: validation
Validate before calling
func validateRemovalRules(rules []string) error {
for _, s := range rules {
if _, err := awstasks.ParseRemovalRule(s); err != nil {
return fmt.Errorf("removeExtraRules entry %q invalid: %v", s, err)
}
}
return nil
}
// or simply run `kops update cluster` (dry-run) which calls FindDeletions and surfaces this before --yes Try / catch
if err := update(); err != nil {
var re *kopsapi.RunError
if errors.As(err, &re) && strings.Contains(err.Error(), "cannot parse rule") {
fixSpecRuleAndRerun()
}
} Prevention
- 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
When it happens
Trigger: 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-").
Common situations: 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.
Related errors
- cannot parse rule %q
- discoveryService URL must be specified
- VPC ID is required when InternetGateway is shared
- AWS partition was empty
- Region is not a recognized EC2 region: %q (check you have sp
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/0f9ecc2b861be04e.
Report an issue: GitHub.