{"record":{"id":"991478e4a8a8dd54","repo":"kubernetes/kops","slug":"must-set-family-when-using-sourceranges","errorCode":null,"errorMessage":"must set Family when using SourceRanges","messagePattern":"must set Family when using SourceRanges","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/gcetasks/firewallrule.go","lineNumber":126,"sourceCode":"\t// this is interpreted as OR, not AND, which is likely not what was intended.\n\tif len(e.SourceRanges) != 0 && len(e.SourceTags) != 0 {\n\t\treturn fmt.Errorf(\"SourceRanges and SourceTags should not both be specified\")\n\t}\n\n\tname := fi.ValueOf(e.Name)\n\n\t// Make sure we've split the ipv4 / ipv6 addresses.\n\t// A single firewall rule can't mix ipv4 and ipv6 addresses, so we split them into two rules.\n\tfor _, sourceRange := range e.SourceRanges {\n\t\t_, cidr, err := net.ParseCIDR(sourceRange)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"sourceRange %q is not valid: %w\", sourceRange, err)\n\t\t}\n\n\t\tif e.Family == \"\" {\n\t\t\t// This is our own requirement, just for consistency checking.\n\t\t\t// Previous we used the name, but that was confused when the cluster name was ipv6.example.com\n\t\t\treturn fmt.Errorf(\"must set Family when using SourceRanges\")\n\t\t}\n\n\t\tif cidr.IP.To4() != nil {\n\t\t\t// IPv4\n\t\t\tif e.Family != AddressFamilyIPv4 {\n\t\t\t\treturn fmt.Errorf(\"ipv4 ranges should not be in a ipv6-named rule (found %s in %s)\", sourceRange, name)\n\t\t\t}\n\t\t} else {\n\t\t\t// IPv6\n\t\t\tif e.Family != AddressFamilyIPv6 {\n\t\t\t\treturn fmt.Errorf(\"ipv6 ranges should be in a ipv6-named rule (found %s in %s)\", sourceRange, name)\n\t\t\t}\n\t\t}\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":108,"sourceCodeEnd":144,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/gcetasks/firewallrule.go#L108-L144","documentation":"kOps requires FirewallRule.Family to be set whenever SourceRanges is used, so it can consistently split rules into IPv4 and IPv6 variants. An empty Family with any SourceRanges entry is a spec validation error.","triggerScenarios":"A firewallRule specifies sourceRanges but leaves the family field empty; Normalize checks e.Family == \"\" right after parsing each CIDR.","commonSituations":"Older cluster manifests written before the Family field existed; hand-written rules omitting the new required field; template generation that never sets family.","solutions":["Set family: ipv4 or family: ipv6 on the FirewallRule to match its ranges","Split IPv4 and IPv6 ranges into two rules with distinct families if mixed","Upgrade/adjust manifest tooling to emit the family field","Re-run kops update"],"exampleFix":"// before\nsourceRanges: [\"10.0.0.0/8\"]\n// after\nfamily: ipv4\nsourceRanges: [\"10.0.0.0/8\"]","handlingStrategy":"validation","validationCode":"if len(rule.SourceRanges) > 0 && rule.Family == \"\" {\n  return fmt.Errorf(\"rule %s: must set family (ipv4|ipv6) when using sourceRanges\", rule.Name)\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set family on every rule that declares sourceRanges","Update stored manifests/kustomizations when upgrading kOps","Derive family from CIDR version in generators"],"tags":["gcp","gce","firewall","ipv6","validation"],"backgroundTag":"missing-address-family","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T12:17:11.808Z"}