{"record":{"id":"da6d508b6c1e42b8","repo":"k3s-io/k3s","slug":"no-ipv6-cidrs-found","errorCode":null,"errorMessage":"no IPv6 CIDRs found","messagePattern":"no IPv6 CIDRs found","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/util/net.go","lineNumber":105,"sourceCode":"// If no IPv6 addresses are found, an error is raised.\nfunc getFirst6(elems []net.IP) (net.IP, error) {\n\tfor _, elem := range elems {\n\t\tif elem != nil && netutils.IsIPv6(elem) {\n\t\t\treturn elem, nil\n\t\t}\n\t}\n\treturn nil, errors.New(\"no IPv6 address found\")\n}\n\n// getFirst6Net returns the first IPv4 network from the list of IP networks.\n// If no IPv6 addresses are found, an error is raised.\nfunc getFirst6Net(elems []*net.IPNet) (*net.IPNet, error) {\n\tfor _, elem := range elems {\n\t\tif elem != nil && netutils.IsIPv6(elem.IP) {\n\t\t\treturn elem, nil\n\t\t}\n\t}\n\treturn nil, errors.New(\"no IPv6 CIDRs found\")\n}\n\n// GetFirst6String returns the first IPv6 address from a list of IP address strings.\n// If no IPv6 addresses are found, an error is raised.\nfunc GetFirst6String(elems []string) (string, error) {\n\tips := []net.IP{}\n\tfor _, elem := range elems {\n\t\tfor _, v := range strings.Split(elem, \",\") {\n\t\t\tips = append(ips, net.ParseIP(v))\n\t\t}\n\t}\n\tip, err := getFirst6(ips)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\treturn ip.String(), nil\n}\n","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/k3s-io/k3s/blob/6ba341e396edc16b8dcae978a7c5e3ac7ee5606e/pkg/util/net.go#L87-L123","documentation":"getFirst6Net scans a []*net.IPNet and returns the first network whose IP is IPv6 (netutils.IsIPv6); if every entry is IPv4 or nil it returns 'no IPv6 CIDRs found'. It backs the exported GetFirst6String/GetFirst6Net helpers used to pick the IPv6 half of a dual-stack CIDR list. Note the doc comment above the function mistakenly says 'first IPv4 network', but the code strictly filters for IPv6.","triggerScenarios":"Calling GetFirst6Net/GetFirst6String (or getFirst6Net internally) with a list that contains no IPv6 network: a single-stack IPv4 list like [10.42.0.0/16], a list with two IPv4 CIDRs, or nil entries. Typical call sites resolve the IPv6 pod/service CIDR in dual-stack code paths.","commonSituations":"Dual-stack wiring assumed but cluster-cidr only holds IPv4; server config downgraded to single-stack while caller still asks for the v6 net; earlier parse failures yielding an empty or v4-only slice.","solutions":["Ensure the CIDR list actually contains a valid IPv6 network (e.g. fd01::/48) alongside the IPv4 one when dual-stack is intended","Pre-check the list with utilsnet.IsDualStackCIDRs or netutils.IsIPv6CIDR and only call the *6* helper when an IPv6 CIDR is present","If the cluster is intentionally IPv4-only, branch around the IPv6 lookup instead of calling getFirst6Net unconditionally"],"exampleFix":"// before\nv6, err := util.GetFirst6Net(cidrs) // fails on IPv4-only lists\n\n// after\ndual, derr := utilsnet.IsDualStackCIDRs(cidrs)\nvar v6 *net.IPNet\nif derr == nil && dual {\n    v6, err = util.GetFirst6Net(cidrs)\n} // else: single-stack, skip IPv6 path","handlingStrategy":"validation","validationCode":"has6 := false\nfor _, c := range cidrs {\n    if c != nil && netutils.IsIPv6(c.IP) {\n        has6 = true\n        break\n    }\n}\nif !has6 {\n    // single-stack: skip the IPv6 lookup path entirely\n}","typeGuard":"func hasIPv6Net(elems []*net.IPNet) bool {\n    for _, e := range elems {\n        if e != nil && netutils.IsIPv6(e.IP) {\n            return true\n        }\n    }\n    return false\n}","tryCatchPattern":null,"preventionTips":["Validate dual-stack CIDR composition (one v4 + one v6) at config load, before any component asks for the v6 net","Treat 'no IPv6 CIDRs found' as a configuration signal: log the input list to make the mismatch obvious","Never assume dual-stack: branch on IsDualStackCIDRs before calling the *6* helpers"],"tags":["network","ipv6","dual-stack","cidr","config"],"backgroundTag":null,"analyzedSha":"6ba341e396edc16b8dcae978a7c5e3ac7ee5606e","analyzedAt":"2026-08-15T16:27:54.286Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}