k3s-io/k3s · error
invalid ip format '%s'
Error message
invalid ip format '%s'
What it means
Inside ParseStringSliceToIPs each input string is split on ',' and every token goes through net.ParseIP; the first token that returns nil (not parseable as IPv4 or IPv6) produces this error naming the offending token. It is also the underlying error surfaced by the 'invalid node-ip' wrapper when parsing node IPs.
Source
Thrown at pkg/util/net.go:184
name = hostname
}
// Use lower case hostname to comply with kubernetes constraint:
// https://github.com/kubernetes/kubernetes/issues/71140
name = strings.ToLower(name)
return name, ips, nil
}
// ParseStringSliceToIPs converts slice of strings that in turn can be lists of comma separated unparsed IP addresses
// into a single slice of net.IP, it returns error if at any point parsing failed
func ParseStringSliceToIPs(s []string) ([]net.IP, error) {
var ips []net.IP
for _, unparsedIP := range s {
for _, v := range strings.Split(unparsedIP, ",") {
ip := net.ParseIP(v)
if ip == nil {
return nil, fmt.Errorf("invalid ip format '%s'", v)
}
ips = append(ips, ip)
}
}
return ips, nil
}
// GetFirstValidIPString returns the first valid address from a list of IP address strings,
// without preference for IP family. If no address are found, an empty string is returned.
func GetFirstValidIPString(s []string) string {
for _, unparsedIP := range s {
for _, v := range strings.Split(unparsedIP, ",") {
if ip := net.ParseIP(v); ip != nil {
return v
}
}
}View on GitHub (pinned to 6ba341e396)
Solutions
- Read the token quoted in the message - it is exactly what failed to parse
- Strip empties and whitespace before parsing: strings.TrimSpace on each token, drop zero-length items
- Allow only literal IPs in whatever field feeds this API; validate in your config layer with net.ParseIP
Example fix
// before
ips, err := util.ParseStringSliceToIPs(cfg.NodeIPs)
// after
cleaned := []string{}
for _, s := range cfg.NodeIPs {
for _, tok := range strings.Split(s, ",") {
if tok = strings.TrimSpace(tok); tok != "" {
cleaned = append(cleaned, tok)
}
}
}
ips, err := util.ParseStringSliceToIPs(cleaned) Defensive patterns
Strategy: validation
Validate before calling
func CleanIPList(in []string) ([]string, error) {
out := []string{}
for _, s := range in {
for _, tok := range strings.Split(s, ",") {
tok = strings.TrimSpace(tok)
if tok == "" {
continue
}
if net.ParseIP(tok) == nil {
return nil, fmt.Errorf("invalid ip format '%s'", tok)
}
out = append(out, tok)
}
}
return out, nil
} Type guard
func isLiteralIP(s string) bool { return net.ParseIP(s) != nil } Try / catch
ips, err := util.ParseStringSliceToIPs(list)
if err != nil {
if strings.Contains(err.Error(), "invalid ip format") {
// the quoted token in the message is the exact bad value; fix the source list
}
return nil, err
} Prevention
- Trim and drop empty tokens before parsing comma-separated IP lists
- Validate user-facing IP inputs with net.ParseIP at the boundary
- Beware templating that renders empty optional values as '' or ','
- Prefer structured config (YAML arrays) over comma-joined strings when possible
When it happens
Trigger: Calling util.ParseStringSliceToIPs with a typo'd address, an empty token (from 'a,,b' or a trailing comma), a CIDR, or a hostname in the list.
Common situations: Helm/CLI templating emitting empty values (',,'); env var interpolation leaving placeholders like '<nodeIP>'; users pasting '10.0.0.1/24' or a DNS name into an IP-only field.
Related errors
- invalid node-ip: %w
- ip: %v is not ipv4 or ipv6
- interface %s does not have a correct global unicast ip: %w
- unable to parse CIDR for interface %s: %w
- multiple global unicast addresses defined for %s, please set
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/fb7b9e6e4a911507.
Report an issue: GitHub.