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

  1. 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`
  2. Validate syntax locally: split on '=' must yield exactly 2 tokens, left token must be exactly "port", both ports must parse with strconv.Atoi
  3. Check kops release notes — the DSL is internal and may have changed between versions
  4. 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

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


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/0f9ecc2b861be04e. Report an issue: GitHub.