netbirdio/netbird · error

list chains: %w

Error message

list chains: %w

What it means

cleanChains could not run ChainExists("mangle", "PREROUTING"). PREROUTING is a built-in chain present whenever the mangle table is loaded, so this error means the iptables invocation itself failed: the iptable_mangle module is not loaded, the process lacks privileges, the binary is missing, or the xtables lock is held. The mangle check guards removal of the NETBIRD-RT-PRE jump and mark rules installed by the router.

Source

Thrown at client/firewall/iptables/acl_linux.go:288

		}

		for _, rule := range m.entries["FORWARD"] {
			err := m.iptablesClient.DeleteIfExists(tableName, "FORWARD", rule...)
			if err != nil {
				log.Errorf("failed to delete rule: %v, %s", rule, err)
			}
		}

		err = m.iptablesClient.ClearAndDeleteChain(tableName, chainNameInputRules)
		if err != nil {
			log.Debugf("failed to clear and delete %s chain: %s", chainNameInputRules, err)
			return err
		}
	}

	ok, err = m.iptablesClient.ChainExists("mangle", "PREROUTING")
	if err != nil {
		return fmt.Errorf("list chains: %w", err)
	}
	if ok {
		for _, rule := range m.entries["PREROUTING"] {
			err := m.iptablesClient.DeleteIfExists("mangle", "PREROUTING", rule...)
			if err != nil {
				log.Errorf("failed to delete rule: %v, %s", rule, err)
			}
		}
	}

	for _, rule := range m.entries[mangleFwdKey] {
		if err := m.iptablesClient.DeleteIfExists(tableMangle, chainFORWARD, rule...); err != nil {
			log.Errorf("failed to delete mangle FORWARD guard rule: %v, %s", rule, err)
		}
	}

	for _, ipsetName := range m.ipsetStore.ipsetNames() {
		if err := m.flushIPSet(ipsetName); err != nil {

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Load the module: `modprobe iptable_mangle` (and ip6table_mangle for v6) or bake it into the kernel/image.
  2. Confirm root/CAP_NET_ADMIN for the daemon.
  3. Check `iptables -t mangle -L` succeeds manually in the same context.
  4. Retry after clearing concurrent iptables users.
Defensive patterns

Strategy: try-catch

Validate before calling

// mangle table must be usable before Reset
out, err := exec.Command("iptables", "-t", "mangle", "-L", "-n").CombinedOutput()
if err != nil {
    return fmt.Errorf("mangle table unavailable (modprobe iptable_mangle?): %s", out)
}

Try / catch

if err := mgr.Reset(); err != nil {
    if strings.Contains(err.Error(), "list chains") {
        // table/binary/privilege issue on the mangle table: surface for module loading
        log.Errorf("mangle chain listing failed: %v; run modprobe iptable_mangle", err)
    }
}

Prevention

When it happens

Trigger: Reset/cleanChains on kernels where mangle support is modular and unloaded (`modprobe iptable_mangle` fixes it); distroless images without iptables; non-root agents; hosts where another daemon holds the lock during cleanup.

Common situations: Minimal cloud/kernel images with iptable_mangle compiled as module and no auto-load triggered (the filter-table usage earlier does not load mangle); hardened containers; embedded devices with trimmed netfilter.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/273ca35e72aeed01. Report an issue: GitHub.