istio/istio · error

failed to add IP %s to ipset %s: %w

Error message

failed to add IP %s to ipset %s: %w

What it means

A thin wrapper around netlink.IpsetAdd: adding an IP entry to a kernel ipset failed. '%s'/'%s' are the IP and set name; '%w' carries the netlink error. In istio-cni these sets (e.g. istio-in-pod/istio-out-pod for ambient interception) drive pod traffic redirect, so failures degrade traffic capture.

Source

Thrown at cni/pkg/ipset/nldeps_linux.go:72

		return nil
	}
	return err
}

func (m *realDeps) destroySet(name string) error {
	err := netlink.IpsetDestroy(name)
	return err
}

func (m *realDeps) addIP(name string, ip netip.Addr, ipProto uint8, comment string, replace bool) error {
	err := netlink.IpsetAdd(name, &netlink.IPSetEntry{
		Comment:  comment,
		IP:       net.IP(ip.AsSlice()),
		Protocol: &ipProto,
		Replace:  replace,
	})
	if err != nil {
		return fmt.Errorf("failed to add IP %s to ipset %s: %w", ip, name, err)
	}
	return nil
}

func (m *realDeps) deleteIP(name string, ip netip.Addr, ipProto uint8) error {
	err := netlink.IpsetDel(name, &netlink.IPSetEntry{
		IP:       net.IP(ip.AsSlice()),
		Protocol: &ipProto,
	})
	if err != nil {
		return fmt.Errorf("failed to delete IP %s from ipset %s: %w", ip, name, err)
	}
	return nil
}

func (m *realDeps) flush(name string) error {
	err := netlink.IpsetFlush(name)
	if err != nil {

View on GitHub (pinned to 8dc789c5cf)

Solutions

  1. Inspect the wrapped netlink error: 'Set cannot be added to' / 'already exists' points to ordering; recreate the set (ipset destroy istio-in-pod; the node agent recreates it).
  2. If 'already exists', ensure callers pass replace=true where re-adding is expected, or clear stale entries first (the wrapper supports comment-based clearing).
  3. Verify the ipset exists before adding: ipset list istio-in-pod.
  4. Check capabilities: the pod needs CAP_NET_ADMIN; on old kernels upgrade or drop the comment feature.

Example fix

// before
err := m.addIP(setName, ip, 0x06, comment, false)
// after: tolerate re-adds during pod churn
err := m.addIP(setName, ip, 0x06, comment, true)
Defensive patterns

Strategy: retry

Validate before calling

ipset list istio-in-pod >/dev/null 2>&1 || echo "set missing; create before adding entries"

Try / catch

// Retry once after recreating the set, idempotently.
if err := deps.AddIP(set, ip, proto, comment, true); err != nil {
    if isNotExist(err) {
        _ = deps.Create(set) // recreate then retry once
        err = deps.AddIP(set, ip, proto, comment, true)
    }
    if err != nil { /* log and surface */ }
}

Prevention

When it happens

Trigger: realDeps.addIP is called (e.g. when a pod is added to an ambient mesh and its IP must be inserted) and the kernel rejects the netlink IPSET_CMD_ADD: set does not exist, entry already exists without replace, protocol mismatch (IPv4 entry into IPv6 set), or permission/netlink communication failure.

Common situations: ipsetCreate was skipped or the set was destroyed concurrently by another agent (iptables-legacy tools, a node cleanup job); kernel ipset revision too old for the 'comment' feature (see the Alpine note in the same file); running without CAP_NET_ADMIN; race between pod deletion and re-add where replace=false and the entry already exists.

Related errors


AI-assisted analysis of istio/istio@8dc789c5cf (2026-08-15). Data as JSON: /api/errors/2d3d9810817c5f2f. Report an issue: GitHub.