cilium/cilium · error

detected duplicate public key. node %q uses same key as exis

Error message

detected duplicate public key. node %q uses same key as existing node %q

What it means

The agent maintains a map from public keys to node names; updatePeer rejects a public key that is already registered to a different node. This prevents two nodes from presenting the same identity, which would break peer routing. Usually indicates cloned nodes or leaked stale state.

Source

Thrown at pkg/wireguard/agent/agent.go:537

	a.Lock()
	defer a.Unlock()
	if a.wgClient == nil {
		return nil
	}

	pubKey, err := wgtypes.ParseKey(pubKeyHex)
	if err != nil {
		return err
	}

	if pubKey == wgDummyPeerKey {
		return fmt.Errorf("node %q is not allowed to use the dummy peer key", nodeName)
	}

	if prevNodeName, ok := a.nodeNameByPubKey[pubKey]; ok {
		if nodeName != prevNodeName {
			return fmt.Errorf("detected duplicate public key. "+
				"node %q uses same key as existing node %q", nodeName, prevNodeName)
		}
	}

	peer := a.peerByNodeName[nodeName]

	// Reinitialize peer if its public key changed.
	if peer != nil && peer.pubKey != pubKey {
		a.logger.Debug(
			"Pubkey has changed",
			logfields.NodeName, nodeName,
		)
		if err := a.deletePeerByPubKey(peer.pubKey); err != nil {
			return err
		}
		peer = nil
	}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Delete the stale private key file (/var/lib/cilium/wg or configured path) on the cloned node and restart the agent to regenerate keys
  2. Ensure the node's identity (name) is stable; fix hostname/K8s node name mismatches
  3. Remove the stale CiliumNode resource for the old node name
  4. If intentional key rotation, remove the old peer mapping first

Example fix

// on the cloned node
// before
rm /var/lib/cilium/wg  # (stop cilium-agent first)
// after
systemctl restart cilium-agent  # generates a fresh key pair
Defensive patterns

Strategy: validation

Validate before calling

func ensureUniqueKey(keyHex, nodeName string, keyToNode map[string]string) error {
    if owner, ok := keyToNode[keyHex]; ok && owner != nodeName {
        return fmt.Errorf("key already owned by node %q", owner)
    }
    return nil
}

Try / catch

if err := updatePeer(nodeName, key); err != nil {
    if strings.Contains(err.Error(), "duplicate public key") {
        // clone detected: force key regeneration on the node
    }
}

Prevention

When it happens

Trigger: Update is called for node B with a public key already mapped to node A in nodeNameByPubKey, e.g. a VM cloned with its /var/lib/cilium/wg private key intact.

Common situations: Node images/VMs cloned without regenerating the WireGuard private key, restoring a node from a snapshot, or DNS/hostname changes making the same node appear under a new name with its old key.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/46c697cd3c18e9c7. Report an issue: GitHub.