cilium/cilium · error

Listener is not allowed on ingress (%s)

Error message

Listener is not allowed on ingress (%s)

What it means

Cilium's policy rule validation rejects a custom Envoy `Listener` on ingress network policy rules. Custom listeners are only supported on the egress path because that is the only path that has been adequately tested; a compile-time-style test flag (TestAllowIngressListener) can override this for testing. The check exists so users do not rely on an untested/unsupported configuration that may silently not enforce policy as expected.

Source

Thrown at pkg/policy/api/rule_validation.go:670

		if isZero {
			haveZeroPort = true
		}
		// DNS L7 rules can be TCP, UDP or ANY, all others are TCP only.
		switch {
		case pr.Rules.IsEmpty(), hasDNSRules:
			// nothing to do if no rules OR they are DNS rules (note the comma above)
		case pr.Ports[i].Protocol != ProtoTCP:
			return fmt.Errorf("L7 rules can only apply to TCP (not %s) except for DNS rules", pr.Ports[i].Protocol)
		}
	}

	listener := pr.Listener
	if listener != nil {
		// For now we have only tested custom listener support on the egress path.  TODO
		// (jrajahalme): Lift this limitation in follow-up work once proper testing has been
		// done on the ingress path.
		if ingress && !TestAllowIngressListener {
			return fmt.Errorf("Listener is not allowed on ingress (%s)", listener.Name)
		}
		// There is no guarantee that Listener will support Cilium policy enforcement.
		if !pr.Rules.IsEmpty() {
			return fmt.Errorf("Listener is not allowed with L7 rules (%s)", listener.Name)
		}
	}

	// Sanitize L7 rules
	if !pr.Rules.IsEmpty() {
		if haveZeroPort {
			return errors.New("L7 rules can not be used when a port is 0")
		}

		if err := pr.Rules.Validate(pr.Ports); err != nil {
			return err
		}
	}
	return nil

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Remove the `listener` field from the ingress rule, keeping it only on egress rules
  2. Move the traffic control the listener provided into an egress rule instead
  3. If this is for CI/testing only, set TestAllowIngressListener=true in the test harness (not production)
  4. If ingress listener support is needed, follow/contrast upstream Cilium issues tracking lifting this limitation

Example fix

// before (ingress rule)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
spec:
  ingress:
  - toPorts:
    - ports: [{port: '8080'}]
      listener: my-envoy-listener
// after
  ingress:
  - toPorts:
    - ports: [{port: '8080'}]
Defensive patterns

Strategy: validation

Validate before calling

func hasIngressListener(rule api.Rule) bool {
	if rule.EndpointSelector != nil && !rule.Ingress(nil, nil) {
		// caller should determine direction; simplest guard: scan ingress port rules
	}
	for _, r := range rule.IngressRules {
		for _, p := range r.ToPorts {
			if p.Listener != nil {
				return true
			}
		}
	}
	return false
}
// reject or strip listener before calling Validate

Try / catch

err := rule.Validate(state, logger)
if err != nil && strings.Contains(err.Error(), "Listener is not allowed on ingress") {
	// strip listener from ingress toPorts or move rule to egress and re-validate
}

Prevention

When it happens

Trigger: Calling PortRule.Validate (via a CiliumNetworkPolicy rule Validate) with a rule whose `listener` field is set while the rule is an ingress rule and TestAllowIngressListener is false.

Common situations: Users copying an egress rule with a `listener:` block into an ingress section of a CiliumNetworkPolicy; tooling generating symmetric ingress/egress rules; upgrading Cilium after using listeners on egress and mirroring them to ingress.

Related errors


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