k3s-io/k3s · error
Node password rejected, duplicate hostname or contents of '%
Error message
Node password rejected, duplicate hostname or contents of '%s' may not match server node-passwd entry, try enabling a unique node name with the --with-node-id flag
What it means
When the agent fetches its configuration from the server over HTTP and gets 403 Forbidden (after the built-in retry without client-certificate auth), this error is returned: the node password stored at nodePasswordFile does not match the server's node-passwd entry for that node name. It usually means another machine with the same hostname registered first, or this node's password file was regenerated while the server still holds the old entry.
Source
Thrown at pkg/agent/config/config.go:180
}
defer resp.Body.Close()
// If we got a 401 Unauthorized response when using client certs, try again without client cert auth.
// This allows us to fall back from node identity to token when the node resource is deleted.
if resp.StatusCode == http.StatusUnauthorized {
if transport, ok := client.Transport.(*http.Transport); ok && transport.TLSClientConfig != nil && len(transport.TLSClientConfig.Certificates) != 0 {
logrus.Infof("Node authorization rejected, retrying without client certificate authentication")
transport.TLSClientConfig.Certificates = []tls.Certificate{}
resp, err = client.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
}
}
if resp.StatusCode == http.StatusForbidden {
return nil, fmt.Errorf("Node password rejected, duplicate hostname or contents of '%s' may not match server node-passwd entry, try enabling a unique node name with the --with-node-id flag", nodePasswordFile)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("%s: %s", u, resp.Status)
}
return io.ReadAll(resp.Body)
}
}
func ensureNodeID(nodeIDFile string) (string, error) {
if _, err := os.Stat(nodeIDFile); err == nil {
id, err := os.ReadFile(nodeIDFile)
return strings.TrimSpace(string(id)), err
}
id := make([]byte, 4, 4)
_, err := cryptorand.Read(id)
if err != nil {View on GitHub (pinned to 6ba341e396)
Solutions
- Start the agent with --with-node-id to append a generated unique id to the node name (the remediation the error text itself suggests)
- Delete the stale node so it can re-register: kubectl delete node <hostname>
- Ensure every node has a unique hostname before joining
- If the node was reinstalled, drain and delete the old entry first, then rejoin
Example fix
# before k3s agent --server https://server:6443 --token mynodetoken # after (cloned/duplicate hostnames) k3s agent --server https://server:6443 --token mynodetoken --with-node-id
Defensive patterns
Strategy: validation
Validate before calling
# before joining, ensure no live Node already owns this hostname:
hostname=$(hostname)
if kubectl get node "$hostname" >/dev/null 2>&1; then
echo "node name collision: delete the old node or use --with-node-id"
fi Try / catch
if err != nil && strings.Contains(err.Error(), "Node password rejected") {
// operational remediation, not a retry: either kubectl delete node <hostname>
// or restart the agent with --with-node-id for duplicate hostnames
} Prevention
- Assign unique hostnames at image/provisioning time (cloud-init, kickstart)
- For cloned VMs, always start agents with --with-node-id
- When reinstalling a node, drain and delete its Node object first
When it happens
Trigger: GET to the agent config URL returns 403: duplicate NODE_NAME in the cluster, cloned VMs reusing a hostname, or the node's /etc/rancher/node/password file recreated (data-dir wiped) while the Node object persists server-side.
Common situations: Cloning VM templates without changing hostnames; re-provisioning nodes with the same name; hostname collisions from DHCP/DNS; reinstalling the OS without deleting the old Node object.
Related errors
- invalid flag use; --server is required with --disable-etcd
- server node name not set
- password hash not found in node secret
- header node name does not match auth node name
- node name not set
AI-assisted analysis of k3s-io/k3s@6ba341e396 (2026-08-15).
Data as JSON: /api/errors/93de1cd1a8c86d81.
Report an issue: GitHub.