netbirdio/netbird · error
add jump rules: %w
Error message
add jump rules: %w
What it means
Returned when addJumpRules() fails during router container setup. It inserts three jump rules (-j NETBIRD-RT-NAT into nat POSTROUTING, -j NETBIRD-RT-PRE into mangle PREROUTING, -j NETBIRD-RT-RDR into nat PREROUTING) at position 1 of built-in chains via go-iptables Insert(). The first failing insert aborts createContainers(), so traffic never reaches NetBird's custom chains and routing/NAT is dead.
Source
Thrown at client/firewall/iptables/router_linux.go:475
if err := r.iptablesClient.NewChain(chainInfo.table, chainInfo.chain); err != nil {
return fmt.Errorf("create chain %s in table %s: %w", chainInfo.chain, chainInfo.table, err)
}
}
if err := r.insertEstablishedRule(chainRTFWDIN); err != nil {
return fmt.Errorf("insert established rule: %w", err)
}
if err := r.insertEstablishedRule(chainRTFWDOUT); err != nil {
return fmt.Errorf("insert established rule: %w", err)
}
if err := r.addPostroutingRules(); err != nil {
return fmt.Errorf("add static nat rules: %w", err)
}
if err := r.addJumpRules(); err != nil {
return fmt.Errorf("add jump rules: %w", err)
}
if err := r.addMSSClampingRules(); err != nil {
log.Errorf("failed to add MSS clamping rules: %s", err)
}
return nil
}
// setupDataPlaneMark configures the fwmark for the data plane
func (r *router) setupDataPlaneMark() error {
var merr *multierror.Error
preRule := []string{
"-i", r.wgIface.Name(),
"-m", "conntrack", "--ctstate", "NEW",
"-j", "CONNMARK", "--set-mark", fmt.Sprintf("%#x", nbnet.DataPlaneMarkIn),
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Run the failing insert manually: `iptables -t mangle -I PREROUTING 1 -j NETBIRD-RT-PRE` and `iptables -t nat -I POSTROUTING 1 -j NETBIRD-RT-NAT` to see stderr
- `modprobe iptable_mangle iptable_nat` (plus ip6table_mangle/ip6table_nat for IPv6)
- Install iptables (iptables-nft) and ensure the same implementation exists for ip6tables when the peer network is dual-stack
- Verify root/CAP_NET_ADMIN: `capsh --print | grep cap_net_admin`
- Retry after releasing /run/xtables.lock (stop docker/firewalld temporarily or rerun `netbird up`)
Example fix
// before: single wrapper hides which of the three jump rules failed
if err := r.addJumpRules(); err != nil {
return fmt.Errorf("add jump rules: %w", err)
}
// after: fail on the first unusable table before mutating built-in chains
for _, t := range []string{"nat", "mangle"} {
if err := r.iptablesClient.List(t, "PREROUTING"); err != nil {
return fmt.Errorf("table %s unusable: %w", t, err)
}
}
if err := r.addJumpRules(); err != nil {
return fmt.Errorf("add jump rules: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
func jumpTargetsReady(ipt *iptables.IPTables) error {
for _, c := range []struct{ table, chain string }{
{"nat", "POSTROUTING"}, {"mangle", "PREROUTING"}, {"nat", "PREROUTING"},
} {
if _, err := ipt.List(c.table, c.chain); err != nil {
return fmt.Errorf("%s/%s not programmable: %w", c.table, c.chain, err)
}
}
return nil
} Type guard
func isExitCode(err error, code int) bool {
var ee *exec.ExitError
return errors.As(err, &ee) && ee.ExitCode() == code
} Try / catch
Wrap addJumpRules failures as fatal for router init; on error, invoke cleanJumpRules + cleanUpDefaultForwardRules to unwind the earlier inserts before propagating.
Prevention
- Preload iptable_mangle and iptable_nat on hosts running routed peers
- Pin one iptables implementation (legacy or nft) system-wide, including ip6tables
- Alert on 'create containers' or 'add jump rules' in agent logs; they always mean routing is down
- Use netbird down before reconfiguring host firewall backends
When it happens
Trigger: router.init() -> addJumpRules() when `iptables -t nat -I POSTROUTING 1 -j NETBIRD-RT-NAT` (or the mangle/nat PREROUTING equivalents) exits non-zero: iptable_mangle module not loaded, nat table absent, CAP_NET_ADMIN missing, xtables.lock contention, or iptables-legacy vs nft family mismatch.
Common situations: Host kernels without iptable_mangle (common in stripped VPS/OpenVZ kernels); agents inside Kubernetes/Docker pods without NET_ADMIN; systems where another tool (Docker, firewalld) rewrites built-in chains concurrently; WSL2 or nftables-only images lacking iptables compat binaries.
Related errors
- add IP to ipset: %w
- failed to check rule: %w
- rule already exists
- failed to delete rule: %s, %v: %w
- list chains: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/00b5186ff52c3e67.
Report an issue: GitHub.