kubernetes/kops · error
ipv4 ranges should not be in a ipv6-named rule (found %s in
Error message
ipv4 ranges should not be in a ipv6-named rule (found %s in %s)
What it means
A single GCE firewall rule cannot mix IPv4 and IPv6 source ranges, so kOps enforces that each entry matches the rule's declared Family. An IPv4 CIDR inside a rule whose Family is AddressFamilyIPv6 triggers this error (and symmetrically for IPv6).
Source
Thrown at upup/pkg/fi/cloudup/gcetasks/firewallrule.go:132
// Make sure we've split the ipv4 / ipv6 addresses.
// A single firewall rule can't mix ipv4 and ipv6 addresses, so we split them into two rules.
for _, sourceRange := range e.SourceRanges {
_, cidr, err := net.ParseCIDR(sourceRange)
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
}View on GitHub (pinned to 4c8573c808)
Solutions
- Move the IPv4 range into a separate rule with family: ipv4
- Or correct family to ipv4 if the rule should be IPv4-only
- Remove the mismatched range if it was added by mistake
- Re-run kops update
Example fix
// before family: ipv6 sourceRanges: ["10.0.0.0/8", "fd00::/8"] // after family: ipv6 sourceRanges: ["fd00::/8"] # plus a second rule with family: ipv4, sourceRanges: ["10.0.0.0/8"]
Defensive patterns
Strategy: validation
Validate before calling
for _, r := range rule.SourceRanges {
_, cidr, _ := net.ParseCIDR(r)
isV4 := cidr.IP.To4() != nil
if (rule.Family == "ipv6" && isV4) || (rule.Family == "ipv4" && !isV4) {
return fmt.Errorf("rule %s: CIDR %q does not match family %s", rule.Name, r, rule.Family)
}
} Prevention
- Never mix v4 and v6 ranges in one GCE rule — GCE forbids it
- Split dual-stack sources into two rules with correct families
- Check To4() on parsed CIDRs in any manifest generator
When it happens
Trigger: e.Family is ipv6 but the loop encounters a CIDR whose cidr.IP.To4() != nil (an IPv4 range, e.g. 10.0.0.0/8 in a rule under an ipv6-named rule).
Common situations: Adding an IPv4 range to an IPv6 rule when enabling dual-stack; wrong family label after copy-paste; tooling that defaults all rules to ipv6 because the cluster name contains ipv6.
Related errors
- must set Family when using SourceRanges
- either SourceRanges or SourceTags should be specified when D
- SourceRanges and SourceTags should not both be specified
- sourceRange %q is not valid: %w
- ipv6 ranges should be in a ipv6-named rule (found %s in %s)
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/1cb841e6e5ad0a75.
Report an issue: GitHub.