k3s-io/k3s · error

ip: %v is not ipv4 or ipv6

Error message

ip: %v is not ipv4 or ipv6

What it means

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.

Source

Thrown at pkg/util/net.go:216

			if ip := net.ParseIP(v); ip != nil {
				return v
			}
		}
	}
	return ""
}

// GetFirstIP checks what is the IPFamily of the first item. Based on that, returns a set of values
func GetDefaultAddresses(nodeIP net.IP) (string, string, string, error) {
	if netutils.IsIPv4(nodeIP) {
		return "0.0.0.0", "10.42.0.0/16", "10.43.0.0/16", nil
	}

	if netutils.IsIPv6(nodeIP) {
		return "::", "fd00:42::/56", "fd00:43::/112", nil
	}

	return "", "", "", fmt.Errorf("ip: %v is not ipv4 or ipv6", nodeIP)
}

// GetFirstString returns the first IP4 address from a list of IP address strings.
// If no IPv4 addresses are found, returns the first IPv6 address
// if neither of IPv4 or IPv6 are found an error is raised.
func GetFirstString(elems []string) (string, bool, error) {
	ip, err := GetFirst4String(elems)
	v6only := false
	if err != nil {
		ip, err = GetFirst6String(elems)
		if err != nil {
			return "", false, err
		}
		v6only = true
	}
	return ip, v6only, nil
}

View on GitHub (pinned to 6ba341e396)

Solutions

  1. Log or assert the input IP right before the call; nil/empty means fix the upstream parse
  2. Ensure the node-ip config is valid so a non-nil IP reaches this function
  3. If the value came from net.ParseIP, check err/ip==nil at that call site first

Example fix

// before
defBind, podCIDR, svcCIDR, err := util.GetDefaultAddresses(ip) // ip may be nil
// after
if ip == nil {
	return fmt.Errorf("node IP is empty")
}
defBind, podCIDR, svcCIDR, err := util.GetDefaultAddresses(ip)
Defensive patterns

Strategy: type-guard

Validate before calling

if ip == nil || !(netutils.IsIPv4(ip) || netutils.IsIPv6(ip)) {
	return fmt.Errorf("node IP %v has no usable family", ip)
}

Type guard

func usableNodeIP(ip net.IP) bool {
	return ip != nil && len(ip) > 0 && (netutils.IsIPv4(ip) || netutils.IsIPv6(ip))
}

Try / catch

bind, podCIDR, svcCIDR, err := util.GetDefaultAddresses(ip)
if err != nil {
	if strings.Contains(err.Error(), "is not ipv4 or ipv6") {
		// nil/garbage IP reached us: fix the upstream parse instead of choosing defaults
		return fmt.Errorf("node IP unset or unparsable: %v", ip)
	}
	return "", "", "", err
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15). Data as JSON: /api/errors/2edf43818bd321d8. Report an issue: GitHub.