k3s-io/k3s · error

invalid node IP address %s

Error message

invalid node IP address %s

What it means

The kubelet serving-cert signing endpoint (pkg/server/handlers/handlers.go) authenticates the requesting node and builds a SAN list from the k3s-Node-IP request header (comma-separated). Each comma-separated value must parse with net.ParseIP; any unparseable value produces this 400 error before a cert is signed. Note the message formats the already-nil parsed value, so it renders as 'invalid node IP address <nil>' rather than showing the bad input.

Source

Thrown at pkg/server/handlers/handlers.go:75

		resp.Header().Set("Content-Length", strconv.Itoa(len(data)))
		resp.Write(data)
	})
}

func ServingKubeletCert(control *config.Control, auth nodepassword.NodeAuthValidator) http.Handler {
	return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) {
		nodeName, errCode, err := auth(req)
		if err != nil {
			util.SendError(err, resp, req, errCode)
			return
		}

		ips := []net.IP{net.ParseIP("127.0.0.1"), net.ParseIP("::1")}
		if nodeIP := req.Header.Get(version.Program + "-Node-IP"); nodeIP != "" {
			for _, v := range strings.Split(nodeIP, ",") {
				ip := net.ParseIP(v)
				if ip == nil {
					util.SendError(fmt.Errorf("invalid node IP address %s", ip), resp, req)
					return
				}
				ips = append(ips, ip)
			}
		}

		signAndSend(resp, req, control.Runtime.ServerCA, control.Runtime.ServerCAKey, control.Runtime.ServingKubeletKey, certutil.Config{
			CommonName: nodeName,
			Usages:     []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth},
			AltNames: certutil.AltNames{
				DNSNames: []string{nodeName, "localhost"},
				IPs:      ips,
			},
		})
	})
}

func ClientKubeletCert(control *config.Control, auth nodepassword.NodeAuthValidator) http.Handler {

View on GitHub (pinned to 6ba341e396)

Solutions

  1. Inspect the agent's flags and correct --node-ip to literal IP addresses only (valid IPv4 or IPv6), no hostnames, ports, brackets, or empty segments.
  2. If multiple IPs are needed, keep the comma list strict: exactly one address per element, no trailing comma or spaces.
  3. Restart the k3s agent so it re-registers with the fixed header.
  4. If templating from config management, assert the value matches an IP regex before deploying.

Example fix

# before
k3s agent --server https://server:6443 --node-ip mynode.example.com,

# after
k3s agent --server https://server:6443 --node-ip 10.0.0.5
Defensive patterns

Strategy: validation

Validate before calling

// Agent-side: validate --node-ip before k3s uses it
for _, s := range strings.Split(nodeIPFlag, ",") {
    if net.ParseIP(strings.TrimSpace(s)) == nil {
        log.Fatalf("invalid --node-ip value %q", s)
    }
}

Type guard

func validNodeIPList(v string) bool {
    if v == "" { return true }
    for _, s := range strings.Split(v, ",") {
        if net.ParseIP(s) == nil { return false }
    }
    return true
}

Prevention

When it happens

Trigger: An agent (or direct HTTP caller) hits /v1-k3s/serving-kubelet-cert with a k3s-Node-IP header containing a value that net.ParseIP rejects: a hostname, a value with whitespace or a port (e.g. 10.0.0.1:10250), an IPv6 with brackets, or an empty string produced by a trailing/duplicated comma.

Common situations: Setting --node-ip with a DNS name or malformed address on k3s agent; shell quoting that appends a stray comma ('--node-ip 10.0.0.1,'); scripts templating the flag from an empty variable; IPv6 addresses passed with surrounding brackets because they came from a URL.

Related errors


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