cilium/cilium · error

interface %q exists in %s but is missing in %s

Error message

interface %q exists in %s but is missing in %s

What it means

Inside validateWireguardStates, compareIfaces iterates each interface in the 'from' list (agent or kernel) and looks up the same-named interface in the 'to' list via findIface. When a WireGuard interface is present on one side but no interface with that name exists on the other, this error is joined into the aggregate result. It indicates agent and kernel fundamentally disagree about which WireGuard devices exist.

Source

Thrown at cilium-dbg/cmd/encrypt_status.go:128

	findIface := func(ifaces []*models.WireguardInterface, name string) *models.WireguardInterface {
		for _, iface := range ifaces {
			if iface.Name == name {
				return iface
			}
		}
		return nil
	}

	compareIfaces := func(from, to []*models.WireguardInterface, fromLabel, toLabel string) {
		for _, f := range from {
			if _, seen := seenIfaces[f.Name]; seen {
				continue
			}
			seenIfaces[f.Name] = struct{}{}

			t := findIface(to, f.Name)
			if t == nil {
				errs = errors.Join(errs, fmt.Errorf("interface %q exists in %s but is missing in %s",
					f.Name, fromLabel, toLabel))
				continue
			}

			if f.PeerCount != t.PeerCount {
				errs = errors.Join(errs, fmt.Errorf("interface %q: peer count mismatch (%s=%d, %s=%d)",
					f.Name, fromLabel, f.PeerCount, toLabel, t.PeerCount))
			}
			if f.ListenPort != t.ListenPort {
				errs = errors.Join(errs, fmt.Errorf("interface %q: listen port mismatch (%s=%d, %s=%d)",
					f.Name, fromLabel, f.ListenPort, toLabel, t.ListenPort))
			}
			if f.PublicKey != t.PublicKey {
				errs = errors.Join(errs, fmt.Errorf("interface %q: public key mismatch (%s=%s, %s=%s)",
					f.Name, fromLabel, f.PublicKey, toLabel, t.PublicKey))
			}
		}
	}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Compare reported names: run `cilium encrypt status` and `ip -d link show type wireguard` to see which side lists the interface; align by restarting the agent to re-sync its view with the kernel.
  2. If the kernel device is genuinely missing, restart the Cilium agent so it recreates cilium_wg0 and repopulates peers.
  3. If an unexpected/renamed device exists, check for config changes (encryption enabled/disabled flapping) and clean up stale interfaces manually (`ip link del <name>`) before restarting the agent.
  4. Run the CLI from the host network namespace as root so wgctrl can see all WireGuard devices.

Example fix

// before: agent knows cilium_wg0, kernel side absent
Msg: wireguard state mismatch...: interface "cilium_wg0" exists in agent but is missing in kernel
// after: restart agent to recreate the device
$ kubectl -n kube-system rollout restart daemonset/cilium
$ cilium encrypt status  # Msg line gone
Defensive patterns

Strategy: validation

Validate before calling

// Pre-check that the interface sets match before detailed comparison
agentNames := map[string]bool{}
for _, i := range agent.Interfaces { agentNames[i.Name] = true }
kernelNames := map[string]bool{}
for _, i := range kernel.Interfaces { kernelNames[i.Name] = true }
for n := range agentNames { if !kernelNames[n] { fmt.Printf("%s missing on kernel side\n", n) } }

Type guard

func ifacePresent(ifaces []*models.WireguardInterface, name string) *models.WireguardInterface {
    for _, i := range ifaces {
        if i.Name == name { return i }
    }
    return nil
}

Try / catch

if err := validateWireguardStates(agent, kernel); err != nil {
    if strings.Contains(err.Error(), "exists in") {
        // interface-set divergence: trigger agent restart/re-sync
    }
}

Prevention

When it happens

Trigger: `cilium encrypt status` in wireguard mode where the agent's healthz Wireguard.Interfaces list and the kernel dump (dumpWireGuardStatus, which reports only the cilium_wg0 device) do not share an interface name — e.g. agent reports cilium_wg0 but the kernel device is absent, or named differently.

Common situations: Agent recreated the interface with a different name after a config change; leftover/stale agent state after interface deletion; the CLI runs in a namespace where the kernel device is not visible so the kernel side list is empty; partial rollout where some nodes run different Cilium versions with different interface naming.

Related errors


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