{"record":{"id":"2edf43818bd321d8","repo":"k3s-io/k3s","slug":"ip-v-is-not-ipv4-or-ipv6","errorCode":null,"errorMessage":"ip: %v is not ipv4 or ipv6","messagePattern":"ip: (.+?) is not ipv4 or ipv6","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/net.go","lineNumber":216,"sourceCode":"\t\t\tif ip := net.ParseIP(v); ip != nil {\n\t\t\t\treturn v\n\t\t\t}\n\t\t}\n\t}\n\treturn \"\"\n}\n\n// GetFirstIP checks what is the IPFamily of the first item. Based on that, returns a set of values\nfunc GetDefaultAddresses(nodeIP net.IP) (string, string, string, error) {\n\tif netutils.IsIPv4(nodeIP) {\n\t\treturn \"0.0.0.0\", \"10.42.0.0/16\", \"10.43.0.0/16\", nil\n\t}\n\n\tif netutils.IsIPv6(nodeIP) {\n\t\treturn \"::\", \"fd00:42::/56\", \"fd00:43::/112\", nil\n\t}\n\n\treturn \"\", \"\", \"\", fmt.Errorf(\"ip: %v is not ipv4 or ipv6\", nodeIP)\n}\n\n// GetFirstString returns the first IP4 address from a list of IP address strings.\n// If no IPv4 addresses are found, returns the first IPv6 address\n// if neither of IPv4 or IPv6 are found an error is raised.\nfunc GetFirstString(elems []string) (string, bool, error) {\n\tip, err := GetFirst4String(elems)\n\tv6only := false\n\tif err != nil {\n\t\tip, err = GetFirst6String(elems)\n\t\tif err != nil {\n\t\t\treturn \"\", false, err\n\t\t}\n\t\tv6only = true\n\t}\n\treturn ip, v6only, nil\n}\n","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/util/net.go#L198-L234","documentation":"GetDefaultAddresses picks cluster defaults based on the family of the node IP: for IPv4 it returns 0.0.0.0 with 10.42.0.0/16 and 10.43.0.0/16; for IPv6 '::' with fd00:42::/56 and fd00:43::/112. If netutils.IsIPv4 and netutils.IsIPv6 are both false - in practice a nil or zero-length net.IP - it refuses to choose defaults.","triggerScenarios":"Calling GetDefaultAddresses with a nil net.IP, typically a net.ParseIP failure whose nil result was not checked upstream, or an unset node-ip that reached this call as nil.","commonSituations":"Code paths where node-ip parsing failed silently upstream; dual-stack edge cases where the IP variable was never assigned; passing net.ParseIP(s) directly without checking the nil return.","solutions":["Log or assert the input IP right before the call; nil/empty means fix the upstream parse","Ensure the node-ip config is valid so a non-nil IP reaches this function","If the value came from net.ParseIP, check err/ip==nil at that call site first"],"exampleFix":"// before\ndefBind, podCIDR, svcCIDR, err := util.GetDefaultAddresses(ip) // ip may be nil\n// after\nif ip == nil {\n\treturn fmt.Errorf(\"node IP is empty\")\n}\ndefBind, podCIDR, svcCIDR, err := util.GetDefaultAddresses(ip)","handlingStrategy":"type-guard","validationCode":"if ip == nil || !(netutils.IsIPv4(ip) || netutils.IsIPv6(ip)) {\n\treturn fmt.Errorf(\"node IP %v has no usable family\", ip)\n}","typeGuard":"func usableNodeIP(ip net.IP) bool {\n\treturn ip != nil && len(ip) > 0 && (netutils.IsIPv4(ip) || netutils.IsIPv6(ip))\n}","tryCatchPattern":"bind, podCIDR, svcCIDR, err := util.GetDefaultAddresses(ip)\nif err != nil {\n\tif strings.Contains(err.Error(), \"is not ipv4 or ipv6\") {\n\t\t// nil/garbage IP reached us: fix the upstream parse instead of choosing defaults\n\t\treturn fmt.Errorf(\"node IP unset or unparsable: %v\", ip)\n\t}\n\treturn \"\", \"\", \"\", err\n}","preventionTips":["Always check the nil return of net.ParseIP before using the result","Guard call sites that derive defaults from an IP with an IsIPv4/IsIPv6 check","Log the effective node IP at startup to catch empty values early"],"tags":["go","network","ip","dual-stack"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}