kubernetes/kops · error

ipv6 ranges should be in a ipv6-named rule (found %s in %s)

Error message

ipv6 ranges should be in a ipv6-named rule (found %s in %s)

What it means

Normalize() on a GCE FirewallRule validates that every source range's IP family matches the rule name's ipv4/ipv6 designation. This error means a CIDR block parsed as IPv6 was placed in a rule whose name does not carry the ipv6 suffix/designation. kOps derives firewall rule names from cluster naming conventions, so the name and the range list must agree.

Source

Thrown at upup/pkg/fi/cloudup/gcetasks/firewallrule.go:137

		if err != nil {
			return fmt.Errorf("sourceRange %q is not valid: %w", sourceRange, err)
		}

		if e.Family == "" {
			// This is our own requirement, just for consistency checking.
			// Previous we used the name, but that was confused when the cluster name was ipv6.example.com
			return fmt.Errorf("must set Family when using SourceRanges")
		}

		if cidr.IP.To4() != nil {
			// IPv4
			if e.Family != AddressFamilyIPv4 {
				return fmt.Errorf("ipv4 ranges should not be in a ipv6-named rule (found %s in %s)", sourceRange, name)
			}
		} else {
			// IPv6
			if e.Family != AddressFamilyIPv6 {
				return fmt.Errorf("ipv6 ranges should be in a ipv6-named rule (found %s in %s)", sourceRange, name)
			}
		}
	}

	return nil
}

func (_ *FirewallRule) CheckChanges(a, e, changes *FirewallRule) error {
	if e.Network == nil {
		return fi.RequiredField("Network")
	}
	return nil
}

func parseFirewallAllowed(rule string) (*compute.FirewallAllowed, error) {
	o := &compute.FirewallAllowed{}

	tokens := strings.Split(rule, ":")

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Rename the firewall rule so it carries the ipv6 designation (include 'ipv6' in the rule name per kOps GCE naming convention).
  2. Change the source range to an IPv4 CIDR if the rule is intended to be IPv4.
  3. If both families are needed, split into two rules: one ipv4-named with IPv4 ranges, one ipv6-named with IPv6 ranges.

Example fix

// before
name: "https-to-nodes"
sourceRanges: ["fd00::/8"]
// after
name: "https-to-nodes-ipv6"
sourceRanges: ["fd00::/8"]
Defensive patterns

Strategy: validation

Validate before calling

func validateFamilyMatchesName(ruleName string, sourceRanges []string) error {
  for _, r := range sourceRanges {
    _, ipnet, err := net.ParseCIDR(r)
    if err != nil { return fmt.Errorf("bad CIDR %q: %w", r, err) }
    isV6 := ipnet.IP.To16() != nil && ipnet.IP.To4() == nil
    nameIsV6 := strings.Contains(ruleName, "ipv6")
    if isV6 != nameIsV6 {
      return fmt.Errorf("range %q (%s) does not match rule name %q", r, family(isV6), ruleName)
    }
  }
  return nil
}

Type guard

func isIPv6CIDR(r string) bool {
  _, ipnet, err := net.ParseCIDR(r)
  return err == nil && ipnet.IP.To4() == nil
}

Prevention

When it happens

Trigger: A FirewallRule task in the cluster spec has a source range like 'fd00::/8' (AddressFamilyIPv6) but the rule name lacks the ipv6 marker; Normalize() is invoked during task validation before rendering to GCE.

Common situations: Hand-edited cluster specs adding IPv6 source ranges to legacy IPv4-named rules; upgrading a cluster to dual-stack without renaming rules; templated manifests where ranges were swapped but names were not.

Related errors


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