k3s-io/k3s · error
interface %s does not have a correct global unicast ip: %w
Error message
interface %s does not have a correct global unicast ip: %w
What it means
GetIPFromInterface wraps any failure of the private getIPFromInterface: interface not found, failure reading its addresses, interface down, an unparseable CIDR, or no global unicast address at all. The wrapper names the interface so you can tell which configured interface name (e.g. a flannel-iface/node-iface style option) failed.
Source
Thrown at pkg/util/net.go:262
return cidr, err
}
// IPStringToIPNet converts an IP string to an IPNet, using a fully filled mask appropriate for the address family.
func IPStringToIPNet(address string) (*net.IPNet, error) {
if strings.Contains(address, ":") {
address += "/128"
} else {
address += "/32"
}
_, cidr, err := net.ParseCIDR(address)
return cidr, err
}
// GetIPFromInterface is the public function that returns the IP of an interface
func GetIPFromInterface(ifaceName string) (string, error) {
ip, err := getIPFromInterface(ifaceName)
if err != nil {
return "", fmt.Errorf("interface %s does not have a correct global unicast ip: %w", ifaceName, err)
}
logrus.Infof("Found ip %s from iface %s", ip, ifaceName)
return ip, nil
}
// getIPFromInterface is the private function that returns de IP of an interface
func getIPFromInterface(ifaceName string) (string, error) {
iface, err := net.InterfaceByName(ifaceName)
if err != nil {
return "", err
}
addrs, err := iface.Addrs()
if err != nil {
return "", err
}
if iface.Flags&net.FlagUp == 0 {
return "", fmt.Errorf("the interface %s is not up", ifaceName)
}View on GitHub (pinned to 6ba341e396)
Solutions
- Confirm the interface exists: ip link show <iface>; if missing, find the real name with ip -o link and fix the config
- If present but unconfigured, assign an address (DHCP or static) and retry - the code requires the interface up with a global unicast address
- On multi-NIC hosts, pin the interface or node-ip explicitly instead of relying on auto-detection
- Re-run and read the wrapped message - it distinguishes not-found vs down vs no-address cases
Defensive patterns
Strategy: validation
Validate before calling
func InterfaceHasGlobalUnicast(name string) error {
iface, err := net.InterfaceByName(name)
if err != nil {
return fmt.Errorf("interface %s not found: %w", name, err)
}
if iface.Flags&net.FlagUp == 0 {
return fmt.Errorf("interface %s is down", name)
}
addrs, err := iface.Addrs()
if err != nil {
return err
}
for _, a := range addrs {
if ip, _, err := net.ParseCIDR(a.String()); err == nil && ip.IsGlobalUnicast() {
return nil
}
}
return fmt.Errorf("interface %s has no global unicast address", name)
} Try / catch
ip, err := util.GetIPFromInterface(cfg.Iface)
if err != nil {
if strings.Contains(err.Error(), "does not have a correct global unicast ip") {
// check existence, link state, and ip addr show <iface> on this host
}
return "", err
} Prevention
- Pin the interface name explicitly in config on multi-NIC hosts
- Verify with ip link show and ip addr show before starting services that derive their IP
- Expect predictable NIC names (ens*, enp*) on modern distros - do not assume eth0
- Add startup readiness checks that wait for the interface to have a global unicast address
When it happens
Trigger: Calling util.GetIPFromInterface("eth1") when eth1 does not exist, exists but is DOWN, has only link-local/loopback addresses, or reports an address the code cannot re-parse as CIDR.
Common situations: Misconfigured interface name ('eth0' on a host using 'ens192'/'enp0s2' predictable names); VMs/cloud images with renamed NICs; addresses arriving late via DHCP so the interface is empty at startup; containers where the expected host interface is not visible.
Related errors
- multiple global unicast addresses defined for %s, please set
- 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/03624b9c434f5163.
Report an issue: GitHub.