netbirdio/netbird · error
source: %w
Error message
source: %w
What it means
Returned by router.applyNetwork (client/firewall/nftables/router_linux.go:2121) when a Network-Set source cannot be turned into nftables expressions. It wraps getIpSet, which increments a refcounted nft Set (ipsetCounter.Increment) and can fail while creating the set ('create or get ipset') or building the lookup expressions - e.g. set with prefixes of the wrong address family for the table, overlapping/unmergeable intervals, oversized element batches, or a netlink failure on AddSet/Flush. The terse 'source:' prefix marks this as the source-side leg; the same helper is reused for destinations.
Source
Thrown at client/firewall/nftables/router_linux.go:2121
}
if err := r.conn.Flush(); err != nil {
return fmt.Errorf("flush delete output DNAT rule: %w", err)
}
delete(r.rules, ruleID)
return nil
}
// applyNetwork generates nftables expressions for networks (CIDR) or sets
func (r *router) applyNetwork(
network firewall.Network,
setPrefixes []netip.Prefix,
isSource bool,
) ([]expr.Any, error) {
if network.IsSet() {
exprs, err := r.getIpSet(network.Set, setPrefixes, isSource)
if err != nil {
return nil, fmt.Errorf("source: %w", err)
}
return exprs, nil
}
if network.IsPrefix() {
return r.applyPrefix(network.Prefix, isSource), nil
}
return nil, nil
}
// applyPrefix generates nftables expressions for a CIDR prefix
func (r *router) applyPrefix(prefix netip.Prefix, isSource bool) []expr.Any {
// dst offset by default
offset := r.af.dstAddrOffset
if isSource {
// src offset
offset = r.af.srcAddrOffsetView on GitHub (pinned to 93e97f4bf1)
Solutions
- Filter the Set's prefixes by address family before calling AddRouteRule so only prefixes matching r.af reach the table
- Ensure overlapping prefixes are merged (firewall.MergeIPRanges is applied in createIpSet) and that the same HashedName always maps to identical prefix contents
- If a stale set with incompatible flags exists, recreate the manager (Create) which rebuilds the work table, then re-add routes
- Batch-check element counts against maxPrefixesSet limits and split very large sets
Example fix
// before
exprs, err := r.getIpSet(network.Set, setPrefixes, isSource)
if err != nil {
return nil, fmt.Errorf("source: %w", err)
}
// after - drop prefixes that do not belong to this table's family
compatible := filterPrefixesForFamily(setPrefixes, r.af.tableFamily == nftables.TableFamilyIPv4)
exprs, err := r.getIpSet(network.Set, compatible, isSource)
if err != nil {
return nil, fmt.Errorf("source: %w", err)
} Defensive patterns
Strategy: validation
Validate before calling
// Keep only prefixes that match the router's family before adding a route
wantV4 := tableFamily == nftables.TableFamilyIPv4
compatible := make([]netip.Prefix, 0, len(setPrefixes))
for _, p := range setPrefixes {
if p.Addr().Is4() == wantV4 {
compatible = append(compatible, p.Masked())
}
}
if len(compatible) == 0 {
return fmt.Errorf("network set %s has no %s prefixes", set.Name(), family)
} Type guard
func prefixesMatchFamily(ps []netip.Prefix, v4 bool) bool {
for _, p := range ps {
if p.Addr().Is4() != v4 {
return false
}
}
return len(ps) > 0
} Try / catch
if _, err := router.AddRouteRule(net, sources, ...); err != nil {
if strings.Contains(err.Error(), "source:") || strings.Contains(err.Error(), "ipset") {
log.Warnf("network set %s unusable on this family, skipping route", net.ID)
continue
}
return err
} Prevention
- Mask and merge overlapping prefixes before submitting sets
- Ensure a given set name always carries identical prefix contents across updates
- Split sets that exceed the element batch limit instead of relying on runtime failure
When it happens
Trigger: A routing/ACL policy whose network Set contains prefixes that do not match the router's address family (v6 prefixes in the IPv4 table); two different Sets hashed to the same nft name with different contents; a Set so large the element batch exceeds netlink limits; Set created previously with incompatible flags (Interval/KeyType) by an older agent version.
Common situations: Management sends a mixed-family distribution group; duplicate network names colliding in HashedName; upgrading the agent while old nft sets persist from the previous version; concurrent route updates racing on the same set name.
Related errors
- apply network -s: %w
- apply network -d: %w
- error adding set %s: %w
- flush error: %w
- error adding prefixes (%d) to set %s: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/8d3d366f3ddeda7c.
Report an issue: GitHub.