netbirdio/netbird · error

apply network -s: %w

Error message

apply network -s: %w

What it means

In addNatRule(), applyNetwork("-s", pair.Source, nil) translates the route pair's source into iptables args. A plain prefix needs no syscall, but a network *set* goes through ipsetCounter.Increment(), which creates/refreshes an ipset via ipset-go. The wrapped 'create or get ipset' failure is therefore usually an ipset-level problem (missing ipset support, CAP_NET_ADMIN, or a set name over the kernel's 31-character limit), not an iptables one.

Source

Thrown at client/firewall/iptables/router_linux.go:689

	}

	markValue := nbnet.PreroutingFwmarkMasquerade
	if pair.Inverse {
		markValue = nbnet.PreroutingFwmarkMasqueradeReturn
	}

	rule := []string{"-i", r.wgIface.Name()}
	if pair.Inverse {
		rule = []string{"!", "-i", r.wgIface.Name()}
	}

	rule = append(rule,
		"-m", "conntrack",
		"--ctstate", "NEW",
	)
	sourceExp, err := r.applyNetwork("-s", pair.Source, nil)
	if err != nil {
		return fmt.Errorf("apply network -s: %w", err)
	}
	destExp, err := r.applyNetwork("-d", pair.Destination, nil)
	if err != nil {
		return fmt.Errorf("apply network -d: %w", err)
	}

	rule = append(rule, sourceExp...)
	rule = append(rule, destExp...)
	rule = append(rule,
		"-j", "MARK", "--set-mark", fmt.Sprintf("%#x", markValue),
	)

	// Ensure nat rules come first, so the mark can be overwritten.
	// Currently overwritten by the dst-type LOCAL rules for redirected traffic.
	if err := r.iptablesClient.Insert(tableMangle, chainRTPRE, 1, rule...); err != nil {
		// TODO: rollback ipset counter
		return fmt.Errorf("error while adding marking rule for %s: %v", pair.Destination, err)
	}

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Check `lsmod | grep ip_set` and load with `modprobe ip_set ip_set_hash_net`
  2. Verify the daemon has CAP_NET_ADMIN; in containers also check that netlink is not seccomp-filtered
  3. Reproduce: `sudo ipset create <name> hash:net family inet` and read the error
  4. Look at the earlier agent logs for 'create or get ipset' with the set name to spot over-length names
  5. Update NetBird: newer agents derive short hashed set names precisely to avoid the 31-char limit

Example fix

// before: set name used as-is, kernel limit not enforced client-side
name := r.ipsetName(network.Set.HashedName())
if _, err := r.ipsetCounter.Increment(name, prefixes); err != nil {
    return nil, fmt.Errorf("create or get ipset: %w", err)
}

// after: validate the name before touching the kernel
name := r.ipsetName(network.Set.HashedName())
if len(name) > 31 {
    return nil, fmt.Errorf("ipset name %q exceeds kernel limit of 31 chars", name)
}
if _, err := r.ipsetCounter.Increment(name, prefixes); err != nil {
    return nil, fmt.Errorf("create or get ipset: %w", err)
}
Defensive patterns

Strategy: validation

Validate before calling

func ipsetUsable() error {
    if _, err := os.Stat("/proc/net/ip_set"); err != nil {
        return fmt.Errorf("ipset subsystem unavailable: %w", err)
    }
    return nil
}

func validSetName(name string) error {
    if len(name) > 31 {
        return fmt.Errorf("ipset name %q exceeds 31 chars", name)
    }
    return nil
}

Try / catch

Catch at the route-apply layer: on 'apply network -s' failures with set-based sources, log the set name and skip that route rather than aborting the whole network-map application; retry on next sync.

Prevention

When it happens

Trigger: pair.Source.IsSet() true and r.ipsetCounter.Increment(name, prefixes) failing: the ipset netlink subsystem is unavailable (ipset module not loaded), the daemon lacks CAP_NET_ADMIN, the hashed set name exceeds the kernel limit, or a previous create left the refcount inconsistent. Only occurs for routes configured with network sets (large routing groups), not plain CIDR pairs.

Common situations: Hosts without the ipset kernel module or ipset tooling (common in minimal containers); management-defined network sets applied to a peer whose kernel lacks ipset; mixed iptables-nft hosts where ipset compatibility is broken; SELinux denying netlink ipset operations.

Related errors


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