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 nilView on GitHub (pinned to ac7b90affa)
Solutions
- Remove the `listener` field from the ingress rule, keeping it only on egress rules
- Move the traffic control the listener provided into an egress rule instead
- If this is for CI/testing only, set TestAllowIngressListener=true in the test harness (not production)
- 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
- Never set `listener` under ingress toPorts in production policies
- Keep listener-based rules in egress sections only
- Add CI linting that flags listener fields in ingress rules
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
- Listener is not allowed with L7 rules (%s)
- authenticating failed by the always-fail auth handler
- Cilium is currently affected by a bug that causes traffic ma
- Rule priority is invalid for the tier
- port 53 must be specified for DNS rules
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/da52f1f65a861aeb.
Report an issue: GitHub.