cilium/cilium · error
interface %s egress: %w
Error message
interface %s egress: %w
What it means
Same family as the ingress failure but for the egress direction: attachSKBProgram failed attaching cil_from_host to cilium_host egress (HANDLE_MIN_EGRESS), wrapped as 'interface %s egress'. It indicates outbound-from-host traffic will not traverse the Cilium BPF programs, breaking host-originated traffic handling. Inner causes mirror the ingress case (qdisc, tcx, pinning, program load).
Source
Thrown at pkg/datapath/loader/host.go:137
return err
}
defer cleanup()
defer hostObj.Close()
// Insert host endpoint policy program.
if err := hostObj.PolicyMap.Update(uint32(ep.GetID()), hostObj.PolicyProg, ebpf.UpdateAny); err != nil {
return fmt.Errorf("inserting host endpoint policy program: %w", err)
}
// Attach cil_to_host to cilium_host ingress.
if err := attachSKBProgram(logger, host, hostObj.ToHost, symbolToHostEp,
bpffsDeviceLinksDir(bpf.CiliumPath(), host), netlink.HANDLE_MIN_INGRESS, option.Config.EnableTCX); err != nil {
return fmt.Errorf("interface %s ingress: %w", ep.InterfaceName(), err)
}
// Attach cil_from_host to cilium_host egress.
if err := attachSKBProgram(logger, host, hostObj.FromHost, symbolFromHostEp,
bpffsDeviceLinksDir(bpf.CiliumPath(), host), netlink.HANDLE_MIN_EGRESS, option.Config.EnableTCX); err != nil {
return fmt.Errorf("interface %s egress: %w", ep.InterfaceName(), err)
}
if err := commit(); err != nil {
return fmt.Errorf("committing bpf pins: %w", err)
}
return nil
}
// ciliumNetConfigs holds functions that yield a BPF configuration object for
// cilium_net.
var ciliumNetConfigs funcRegistry[func(endpoint.Config, *config.Config, netlink.Link) any]
// ciliumNetRenames holds functions that yield BPF map renames for cilium_net.
var ciliumNetRenames funcRegistry[func(endpoint.Config, *config.Config, netlink.Link) map[string]string]
// ciliumNetConfiguration returns a slice of BPF configuration objects yielded
// by all registered config providers of [ciliumNetConfigs].View on GitHub (pinned to ac7b90affa)
Solutions
- Check `tc filter show dev cilium_host egress` for stale or conflicting filters; `tc qdisc del dev cilium_host clsact` and let the agent recreate it.
- Verify kernel support for the chosen attach mode; disable --enable-tcx on kernels < 6.6.
- Clear stale egress link pins under the device's bpffs links dir and restart the agent for a clean attach.
- Confirm CAP_NET_ADMIN/CAP_BPF privileges for egress qdisc and link operations.
- Inspect errors.Is/Unwrap on the wrapped error to distinguish EEXIST (stale pin) from EPERM (permissions) before cleanup.
Example fix
// before: reload leaves half-attached device after egress failure
// agent logs: attaching cilium_host: interface cilium_host egress: ...
// after: clean device hooks before retrying reload
exec.Command("tc", "qdisc", "del", "dev", "cilium_host", "clsact").Run()
os.RemoveAll(bpffsDeviceLinksDir("/sys/fs/bpf/cilium", host))
// then restart cilium-agent to re-run reloadHostEndpoint Defensive patterns
Strategy: retry
Validate before calling
// Pre-check both hooks before reload to avoid half-attached state
func canAttachBothDirections(dev string, enableTCX bool) error {
if enableTCX && !kernelHasTCX() {
return errors.New("tcx egress unsupported on this kernel")
}
filters, err := safenetlink.FilterList(nil, netlink.MakeHandle(0xffff, 0))
if err != nil {
return fmt.Errorf("cannot inspect egress filters: %w", err)
}
_ = filters
return nil
} Type guard
func isEgressAttachError(err error) bool {
return strings.Contains(err.Error(), "egress") &&
(errors.Is(err, unix.EEXIST) || errors.Is(err, unix.EPERM) ||
errors.Is(err, unix.ENOSYS))
} Try / catch
if err := reload(); err != nil {
if isEgressAttachError(err) {
// clean egress hook and retry with backoff
detachEgress("cilium_host")
err = retryWithBackoff(reload, 3)
}
if err != nil {
// last resort: full datapath resync
triggerFullDatapathResync()
}
} Prevention
- Retry with backoff — egress attach can fail transiently during qdisc churn.
- After a failed reload, clean both ingress and egress hooks to avoid half-attached devices.
- Keep kernel and --enable-tcx setting aligned (6.6+ for TCX).
- Remove stale egress link pins before agent restarts after crashes.
- Monitor 'interface %s egress' errors as indicators of node network reconfiguration conflicts.
When it happens
Trigger: attachCiliumHost's second attachSKBProgram call (hostObj.FromHost, symbolFromHostEp, netlink.HANDLE_MIN_EGRESS, option.Config.EnableTCX) errors after ingress succeeded: egress hook unsupported, tcx egress link creation fails, bpffs pin conflict for the egress link path, or EPERM on qdisc operation.
Common situations: Half-attached state after a partial failure (ingress OK, egress fails) leaving stale ingress links to clean; kernel without egress tc support combined with --enable-tcx; pinned egress links left from a previous agent version under /sys/fs/bpf/cilium; netlink qdisc churn during node network reconfiguration.
Related errors
- interface %s ingress: %w
- interface %s ingress: %w
- interface %s egress: %w
- failed to delete ingress qdisc of link %s: %w
- interface %s ingress: %w
AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31).
Data as JSON: /api/errors/507d238aa97f8e76.
Report an issue: GitHub.