cilium/cilium · error

failed to flush ip6tables chain %s: %w

Error message

failed to flush ip6tables chain %s: %w

What it means

Returned by deleteInPodChains when iptables.ClearChain (flush) fails for an ip6tables chain (InpodPreroutingChain or InpodOutputChain) while tearing down ztunnel in-pod rules. Flushing precedes chain deletion so the kernel allows removal; this error means the flush itself failed, and the wrap preserves the underlying ip6tables error.

Source

Thrown at pkg/ztunnel/iptables/inpod.go:507

				_ = ipt6.Delete(table, mainChain, "-j", customChain)
			}
		}
	}

	// Then flush and delete the custom chains
	for _, table := range []string{"mangle", "nat"} {
		for _, chain := range []string{InpodPreroutingChain, InpodOutputChain} {
			if ipv4Enabled {
				if err := ipt4.ClearChain(table, chain); err != nil {
					return fmt.Errorf("failed to flush iptables chain %s: %w", chain, err)
				}
				if err := ipt4.DeleteChain(table, chain); err != nil {
					return fmt.Errorf("failed to delete iptables chain %s: %w", chain, err)
				}
			}
			if ipv6Enabled {
				if err := ipt6.ClearChain(table, chain); err != nil {
					return fmt.Errorf("failed to flush ip6tables chain %s: %w", chain, err)
				}
				if err := ipt6.DeleteChain(table, chain); err != nil {
					return fmt.Errorf("failed to delete ip6tables chain %s: %w", chain, err)
				}
			}
		}
	}
	return nil
}

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Verify IPv6 is actually usable on the node (ip -6 addr, 'ip6tables -L' works) or disable IPv6 in the Cilium/ztunnel config so this branch is skipped.
  2. Install the ip6tables package in the agent container image.
  3. Grant NET_ADMIN capability to the istio-cni/ztunnel pod.
  4. Load required kernel modules (ip6_tables, ip6table_filter, nf_conntrack) on the host.
  5. Check 'dmesg' for module load failures if the underlying error mentions permission/module issues.

Example fix

// before: teardown hard-fails when ip6tables is unusable
if err := ipt6.ClearChain(table, chain); err != nil {
    return fmt.Errorf("failed to flush ip6tables chain %s: %w", chain, err)
}
// after: skip IPv6 chains when IPv6 is disabled/unavailable on the host
if !ipv6Enabled || !ipv6Supported() {
    continue
}
if err := ipt6.ClearChain(table, chain); err != nil {
    return fmt.Errorf("failed to flush ip6tables chain %s: %w", chain, err)
}
Defensive patterns

Strategy: validation

Validate before calling

// confirm ip6tables works before enabling IPv6 inpod rules
func ipv6Supported() bool {
    if err := exec.Command("ip6tables", "-L", "-n").Run(); err != nil {
        return false
    }
    if b, err := os.ReadFile("/proc/sys/net/ipv6/conf/all/disable_ipv6"); err == nil {
        return strings.TrimSpace(string(b)) == "0"
    }
    return false
}

Try / catch

err := ztunnel.DeleteInPodRules(podNetns, cfg)
if err != nil && strings.Contains(err.Error(), "failed to flush ip6tables chain") {
    log.Warnw("ip6tables flush failed; IPv6 rules may be stale", "err", err)
    // degrade: continue with IPv4-only cleanup or retry with backoff
    return retryWithBackoff(deleteV6Chains)
}

Prevention

When it happens

Trigger: Calling DeleteInPodRules with IPv6 enabled when the IPv6 iptables subsystem is unavailable (kernel without CONFIG_IP6_NF_* modules), ip6tables binary missing from the image, or permission denied (missing CAP_NET_ADMIN) during the ClearChain call.

Common situations: Hosts with IPv6 disabled in sysctl but Cilium's IPv6 inpod interception enabled; container images missing the ip6tables binary; minimal kernels (e.g. some GKE/Bottlerocket variants) without ip6tables filter-table support; pods dropped NET_ADMIN.

Related errors


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