k3s-io/k3s · error
multiple global unicast addresses defined for %s, please set
Error message
multiple global unicast addresses defined for %s, please set ip from one of %v
What it means
After collecting global unicast IPv4 and IPv6 addresses on the interface, if more than one IPv4 global unicast exists the function refuses to guess which one to use and lists the candidates in the error. This prevents silently binding the node/cluster to the wrong IP on multi-homed hosts.
Source
Thrown at pkg/util/net.go:302
for _, addr := range addrs {
ip, _, err := net.ParseCIDR(addr.String())
if err != nil {
return "", fmt.Errorf("unable to parse CIDR for interface %s: %w", iface.Name, err)
}
// if not IPv4 adding it on IPv6 list
if ip.To4() == nil {
if ip.IsGlobalUnicast() {
globalUnicastsIPv6 = append(globalUnicastsIPv6, ip.String())
}
continue
}
if ip.IsGlobalUnicast() {
globalUnicasts = append(globalUnicasts, ip.String())
}
}
if len(globalUnicasts) > 1 {
return "", fmt.Errorf("multiple global unicast addresses defined for %s, please set ip from one of %v", ifaceName, globalUnicasts)
}
if len(globalUnicasts) == 1 && len(globalUnicastsIPv6) == 0 {
return globalUnicasts[0], nil
} else if len(globalUnicastsIPv6) > 0 && len(globalUnicasts) == 1 {
return globalUnicasts[0] + "," + globalUnicastsIPv6[0], nil
} else if len(globalUnicastsIPv6) > 0 {
return globalUnicastsIPv6[0], nil
}
return "", fmt.Errorf("can't find ip for interface %s", ifaceName)
}
type multiListener struct {
listeners []net.Listener
closing chan struct{}
conns chan acceptRes
}
View on GitHub (pinned to 6ba341e396)
Solutions
- Pick one explicitly: set the node-ip (or equivalent bind-address) config to one of the candidates listed in the error
- Remove the extra address from that interface if it is not needed
- Point the interface option at a dedicated interface that has exactly one global unicast address
Example fix
# before --flannel-iface=eth0 # eth0 holds 10.0.0.5 and 192.0.2.7 # after --node-ip=10.0.0.5
Defensive patterns
Strategy: validation
Validate before calling
func countIPv4GlobalUnicasts(name string) ([]string, error) {
iface, err := net.InterfaceByName(name)
if err != nil {
return nil, err
}
addrs, _ := iface.Addrs()
found := []string{}
for _, a := range addrs {
if ip, _, err := net.ParseCIDR(a.String()); err == nil && ip.To4() != nil && ip.IsGlobalUnicast() {
found = append(found, ip.String())
}
}
if len(found) > 1 {
return nil, fmt.Errorf("ambiguous: %v - set node-ip explicitly", found)
}
return found, nil
} Try / catch
ip, err := util.GetIPFromInterface(cfg.Iface)
if err != nil && strings.Contains(err.Error(), "multiple global unicast addresses") {
// candidates are listed in the error; require an explicit node-ip in config
return "", fmt.Errorf("%w: set --node-ip explicitly", err)
} Prevention
- Always set node-ip explicitly on hosts that carry floating/secondary IPs
- Keep cluster traffic off interfaces that host VIPs or LB addresses
- Audit ip addr show before adding elastic/floating IPs to a cluster node
When it happens
Trigger: util.GetIPFromInterface on an interface with two or more public IPv4 addresses: secondary elastic IPs, floating IPs, IP aliases, or multi-homed NICs.
Common situations: Cloud nodes with extra EIPs (AWS) or floating IPs (Hetzner); load-balancer VIPs placed on the same NIC; addresses left by a CNI or metallb on the wrong interface; bare-metal hosts with multiple subnets on one interface.
Related errors
- interface %s does not have a correct global unicast ip: %w
- invalid node-ip: %w
- invalid ip format '%s'
- the interface %s is not up
- unable to parse CIDR for interface %s: %w
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/0f78f908ee8f110c.
Report an issue: GitHub.