k3s-io/k3s · error
no IPv6 CIDRs found
Error message
no IPv6 CIDRs found
What it means
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.
Source
Thrown at pkg/util/net.go:105
// If no IPv6 addresses are found, an error is raised.
func getFirst6(elems []net.IP) (net.IP, error) {
for _, elem := range elems {
if elem != nil && netutils.IsIPv6(elem) {
return elem, nil
}
}
return nil, errors.New("no IPv6 address found")
}
// getFirst6Net returns the first IPv4 network from the list of IP networks.
// If no IPv6 addresses are found, an error is raised.
func getFirst6Net(elems []*net.IPNet) (*net.IPNet, error) {
for _, elem := range elems {
if elem != nil && netutils.IsIPv6(elem.IP) {
return elem, nil
}
}
return nil, errors.New("no IPv6 CIDRs found")
}
// GetFirst6String returns the first IPv6 address from a list of IP address strings.
// If no IPv6 addresses are found, an error is raised.
func GetFirst6String(elems []string) (string, error) {
ips := []net.IP{}
for _, elem := range elems {
for _, v := range strings.Split(elem, ",") {
ips = append(ips, net.ParseIP(v))
}
}
ip, err := getFirst6(ips)
if err != nil {
return "", err
}
return ip.String(), nil
}
View on GitHub (pinned to 6ba341e396)
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
Example fix
// before
v6, err := util.GetFirst6Net(cidrs) // fails on IPv4-only lists
// after
dual, derr := utilsnet.IsDualStackCIDRs(cidrs)
var v6 *net.IPNet
if derr == nil && dual {
v6, err = util.GetFirst6Net(cidrs)
} // else: single-stack, skip IPv6 path Defensive patterns
Strategy: validation
Validate before calling
has6 := false
for _, c := range cidrs {
if c != nil && netutils.IsIPv6(c.IP) {
has6 = true
break
}
}
if !has6 {
// single-stack: skip the IPv6 lookup path entirely
} Type guard
func hasIPv6Net(elems []*net.IPNet) bool {
for _, e := range elems {
if e != nil && netutils.IsIPv6(e.IP) {
return true
}
}
return false
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- cluster-cidr: %v and service-cidr: %v, must share the same I
- no IPv4 CIDRs found
- no IPv6 address found
- dual-stack or IPv6 are not supported on Windows node
- no IPv4 address found
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/da6d508b6c1e42b8.
Report an issue: GitHub.