cilium/cilium · error

invalid selector in CiliumNodeConfig %s: %w

Error message

invalid selector in CiliumNodeConfig %s: %w

What it means

Each listed CiliumNodeConfig's Spec.NodeSelector is converted to a label Selector via metav1.LabelSelectorAsSelector to test whether it matches this node's labels. Conversion of a valid stored CR is considered unreachable, but if it fails this error wraps the invalid selector, skipping all CNC matching.

Source

Thrown at pkg/option/resolver/resolver.go:310

		return nil, nil, fmt.Errorf("could not get Node %s: %w", nodeName, err)
	}

	matching := map[string]ciliumv2.CiliumNodeConfig{}

	// track names separately, since we will compute "priority" by lexicographic sort
	var matchingNames []string

	for _, override := range overrides {
		// ignore empty overrides
		if len(override.Spec.Defaults) == 0 {
			continue
		}

		// if we're selecting on a list, then evaluate the node selector
		if name == "" && override.Spec.NodeSelector != nil {
			ls, err := metav1.LabelSelectorAsSelector(override.Spec.NodeSelector)
			if err != nil { // unreachable
				return nil, nil, fmt.Errorf("invalid selector in CiliumNodeConfig %s: %w", override.Name, err)
			}
			if ls.Matches(labels.Set(node.Labels)) {
				matching[override.Name] = override
				matchingNames = append(matchingNames, override.Name)
			}
		} else if name != "" {
			matching[override.Name] = override
			matchingNames = append(matchingNames, override.Name)
		}
	}

	// Within overrides, lexicographical ordering determines priority.
	slices.Sort(matchingNames)

	out := make(map[string]string)
	for _, name := range matchingNames {
		for k, v := range matching[name].Spec.Defaults {
			if errs := apivalidation.IsConfigMapKey(k); len(errs) > 0 {

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Fix the NodeSelector on the offending CiliumNodeConfig (the name is in the message): use valid keys, values, and operators (In, NotIn, Exists, DoesNotExist)
  2. Validate with kubectl: kubectl get ciliumnodeconfig <name> -o yaml and check spec.nodeSelector
  3. Re-create the CR via kubectl apply so API validation runs
  4. Upgrade cilium/client-go so LabelSelectorAsSelector handles the schema version in use

Example fix

// before
nodeSelector:
  matchExpressions:
  - key: kubernetes.io/os
    operator: equals   # invalid operator
    values: [linux]
// after
nodeSelector:
  matchExpressions:
  - key: kubernetes.io/os
    operator: In
    values: [linux]
Defensive patterns

Strategy: validation

Validate before calling

// Go: validate selectors of referenced CNCs before resolving
l, _ := client.CiliumV2().CiliumNodeConfigs(ns).List(ctx, metav1.ListOptions{})
for _, c := range l.Items {
    if c.Spec.NodeSelector != nil {
        if _, err := metav1.LabelSelectorAsSelector(c.Spec.NodeSelector); err != nil {
            return fmt.Errorf("CNC %s has invalid nodeSelector: %w", c.Name, err)
        }
    }
}

Try / catch

cfg, sources, err := resolver.ReadConfigSource(ctx, logger, client, nodeName, source)
if err != nil {
    if strings.Contains(err.Error(), "invalid selector in CiliumNodeConfig") {
        logger.Error("fix the NodeSelector on the named CiliumNodeConfig", "err", err)
    }
    return err
}

Prevention

When it happens

Trigger: LabelSelectorAsSelector returns an error, e.g. selector containing invalid keys/values that bypass API validation (hand-crafted CRs, direct etcd writes, or CRs created before validation was enforced).

Common situations: CiliumNodeConfig objects created via a client that skipped server-side selector validation, CRs copied from other resources with malformed matchExpressions (bad operator names), or cluster upgrade mixing schema versions.

Related errors


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