netbirdio/netbird · warning
check chain %s in table %s: %w
Error message
check chain %s in table %s: %w
What it means
Returned by router.cleanUpDefaultForwardRules inside its loop over the seven NetBird custom chains (NETBIRD-RT-FWD-IN/OUT in filter, NETBIRD-RT-PRE and NETBIRD-RT-MSSCLAMP in mangle, NETBIRD-RT-NAT/RDR/NAT-OUTPUT in nat) when iptablesClient.ChainExists errors for one of them. Like error 554 this is a failed query about the chain, not the chain being absent (absent returns ok=false and is skipped).
Source
Thrown at client/firewall/iptables/router_linux.go:428
log.Debugf("clean OUTPUT jump rule: %v", err)
}
}
for _, chainInfo := range []struct {
chain string
table string
}{
{chainRTFWDIN, tableFilter},
{chainRTFWDOUT, tableFilter},
{chainRTPRE, tableMangle},
{chainRTNAT, tableNat},
{chainRTRDR, tableNat},
{chainNATOutput, tableNat},
{chainRTMSSCLAMP, tableMangle},
} {
ok, err := r.iptablesClient.ChainExists(chainInfo.table, chainInfo.chain)
if err != nil {
return fmt.Errorf("check chain %s in table %s: %w", chainInfo.chain, chainInfo.table, err)
} else if ok {
if err = r.iptablesClient.ClearAndDeleteChain(chainInfo.table, chainInfo.chain); err != nil {
return fmt.Errorf("clear and delete chain %s in table %s: %w", chainInfo.chain, chainInfo.table, err)
}
}
}
return nil
}
func (r *router) createContainers() error {
for _, chainInfo := range []struct {
chain string
table string
}{
{chainRTFWDIN, tableFilter},
{chainRTFWDOUT, tableFilter},
{chainRTPRE, tableMangle},View on GitHub (pinned to 93e97f4bf1)
Solutions
- Reproduce per table: sudo iptables -S; sudo iptables -t nat -S; sudo iptables -t mangle -S
- Install/verify iptables + conntrack/nft packages in containers
- Load table support (modprobe iptable_nat iptable_mangle iptable_filter) or enable in kernel config
- Retry agent start once lock contention clears
Defensive patterns
Strategy: fallback
Validate before calling
# verify every table the manager touches is listable for t in filter nat mangle; do sudo iptables -t $t -S >/dev/null || echo "table $t broken"; done
Try / catch
ok, err := r.iptablesClient.ChainExists(chainInfo.table, chainInfo.chain)
if err != nil {
// record and continue: a broken query on one table should not skip the rest
merr = multierror.Append(merr, fmt.Errorf("check chain %s in table %s: %w", chainInfo.chain, chainInfo.table, err))
continue
} Prevention
- Enable iptable_filter/nat/mangle in kernel or container image
- Run table probes as a preflight in deployment
- Collect per-table errors instead of aborting the loop
When it happens
Trigger: Init cleanup or Reset iterating the chain list; the ChainExists lookup on one table/chain fails because the iptables binary cannot execute or list that table (missing kernel table support, lock, permissions).
Common situations: Minimal kernels without nat/mangle table support (some containers, WSL1-era); iptables-nft with a broken ruleset; lock contention with other firewall tooling during startup.
Related errors
- list chains: %w
- destroy set %s: %w
- remove nat rule: %w
- remove inverse nat rule: %w
- remove legacy routing rule: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/22fdfe3d828cf8e4.
Report an issue: GitHub.