cilium/cilium · error

%w: %s on pools %s and %s

Error message

%w: %s on pools %s and %s

What it means

validateFilters rejects pool configs where the same interface name (IfName) appears in more than one CiliumNetworkDriverDevicePoolConfig. It wraps errIfNameInMultiplePools and names the offending interface and both conflicting pools. An interface can only belong to a single pool.

Source

Thrown at pkg/networkdriver/config.go:21

package networkdriver

import (
	"errors"
	"fmt"
	"slices"

	"github.com/cilium/cilium/pkg/k8s/apis/cilium.io/v2alpha1"
)

// validateFilters ensures that we do not have more than one filter matching the same device.
// some filter fields can be shared among devices (ex: driver, vendor, device id, pf name), but others
// can't (ex: ifname, pciaddr).
func validateFilters(this v2alpha1.CiliumNetworkDriverDevicePoolConfig, others ...v2alpha1.CiliumNetworkDriverDevicePoolConfig) error {
	for _, ifname := range this.Filter.IfNames {
		for _, otherPool := range others {
			if slices.Contains(otherPool.Filter.IfNames, ifname) {
				return fmt.Errorf("%w: %s on pools %s and %s", errIfNameInMultiplePools, ifname, this.PoolName, otherPool.PoolName)
			}
		}
	}

	return nil
}

// validatePools ensures that there are not any conflicting pool definitions.
func validatePools(this v2alpha1.CiliumNetworkDriverDevicePoolConfig, others ...v2alpha1.CiliumNetworkDriverDevicePoolConfig) error {
	for _, p := range others {
		if this.PoolName == p.PoolName {
			return fmt.Errorf("%w: %s", errDuplicatedPoolName, this.PoolName)
		}

		if err := validateFilters(this, others...); err != nil {
			return err
		}
	}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Remove the duplicated ifName from one of the pools' filter.ifNames lists
  2. Give each pool a disjoint set of interface names so filters don't overlap
  3. Use shared fields (driver, vendor, deviceId, pfName) for grouping, but keep exclusive fields like ifName/pciAddr unique per pool

Example fix

// before
pools:
- name: pool-a
  filter: {ifNames: [eth1, eth2]}
- name: pool-b
  filter: {ifNames: [eth1, eth3]}
// after
pools:
- name: pool-a
  filter: {ifNames: [eth1, eth2]}
- name: pool-b
  filter: {ifNames: [eth3, eth4]}
Defensive patterns

Strategy: validation

Validate before calling

func ifNamesDisjoint(pools []v2alpha1.CiliumNetworkDriverDevicePoolConfig) error {
    seen := map[string]string{}
    for _, p := range pools {
        for _, n := range p.Filter.IfNames {
            if owner, ok := seen[n]; ok {
                return fmt.Errorf("ifname %s in pools %s and %s", n, owner, p.PoolName)
            }
            seen[n] = p.PoolName
        }
    }
    return nil
}

Try / catch

if err := validateConfig(cfg); err != nil {
    if errors.Is(err, errIfNameInMultiplePools) {
        // surface which pools conflict; abort apply
    }
    return err
}

Prevention

When it happens

Trigger: Two device pools in the CiliumNetworkDriver config list the same entry in spec.pools[].filter.ifNames; validateFilters is invoked from validatePools while checking one pool against all others.

Common situations: Copy-pasting a pool definition and forgetting to change the ifNames filter; merging two configs where both claim e.g. eth1; typo'd ifname that coincidentally matches another pool's entry.

Related errors


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