netbirdio/netbird · error

create set %s: %w

Error message

create set %s: %w

What it means

Returned by router.createIpSet in the NetBird iptables firewall manager when the kernel refuses to create an ipset. It wraps createIPSet, which calls ipset.Create (lrh3321/ipset-go, netlink) with TypeHashNet, Replace:true and FamilyIPV6 on the v6 router. Creating a set requires root privileges (CAP_NET_ADMIN), the nfnetlink/ip_set/ip_set_hash_net kernel modules, and a valid set name (kernel limit 31 chars).

Source

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

		}
	}

	return nberrors.FormatErrorOrNil(merr)
}

func (r *router) findSets(rule []string) []string {
	var sets []string
	for i, arg := range rule {
		if arg == "-m" && i+3 < len(rule) && rule[i+1] == "set" && rule[i+2] == matchSet {
			sets = append(sets, rule[i+3])
		}
	}
	return sets
}

func (r *router) createIpSet(setName string, sources []netip.Prefix) error {
	if err := r.createIPSet(setName); err != nil {
		return fmt.Errorf("create set %s: %w", setName, err)
	}

	for _, prefix := range sources {
		if err := r.addPrefixToIPSet(setName, prefix); err != nil {
			return fmt.Errorf("add element to set %s: %w", setName, err)
		}
	}

	return nil
}

func (r *router) deleteIpSet(setName string) error {
	if err := r.destroyIPSet(setName); err != nil {
		return fmt.Errorf("destroy set %s: %w", setName, err)
	}

	log.Debugf("Deleted unused ipset %s", setName)
	return nil

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Run the agent as root, and in containers add NET_ADMIN (docker run --cap-add NET_ADMIN)
  2. Load kernel modules: modprobe nfnetlink ipset ip_set_hash_net (or check CONFIG_IP_SET in kernel config)
  3. Verify manual creation works: sudo ipset create probe hash:net && sudo ipset destroy probe
  4. Check dmesg/journal for netlink 'Operation not permitted' or 'No such file or directory' module errors
  5. Confirm no other netbird instance already owns the set names (ipset list -t)

Example fix

# before: container without netfilter rights
docker run netbird/netbird up
# after
docker run --cap-add NET_ADMIN --sysctl net.ipv4.ip_forward=1 netbird/netbird up
Defensive patterns

Strategy: validation

Validate before calling

// probe ipset support before starting the route firewall
func ipsetAvailable() error {
	if os.Geteuid() != 0 {
		return fmt.Errorf("agent must run as root for ipset management")
	}
	const probe = "nb-probe-set"
	if err := ipset.Create(probe, ipset.TypeHashNet, ipset.CreateOptions{Replace: true}); err != nil {
		return fmt.Errorf("ipset create probe: %w", err)
	}
	return ipset.Destroy(probe)
}

Prevention

When it happens

Trigger: AddRouteFiltering (or refcounter.Increment from UpdateSet) with more than one source prefix makes the router create a 'nb-route-<id>[-v6]' hash:net set. It fails when: the agent lacks CAP_NET_ADMIN (container without NET_ADMIN, or not run via sudo); the ipset kernel modules/CONFIG_IP_SET are absent; netlink is unavailable in the sandbox; or the generated name exceeds the kernel ipset name limit.

Common situations: Running netbird up in Docker/LXC without --cap-add NET_ADMIN; minimal cloud/WSL2 kernels without ipset modules; hosts where ipset was never loaded (verify with 'lsmod | grep ip_set'); environments where a third party already created a conflicting set name.

Related errors


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