{"record":{"id":"a0e1fb6ea856889e","repo":"netbirdio/netbird","slug":"error-adding-set-s-w","errorCode":null,"errorMessage":"error adding set %s: %w","messagePattern":"error adding set (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/nftables/router_linux.go","lineNumber":562,"sourceCode":"\tprefixes := firewall.MergeIPRanges(input.prefixes)\n\n\tnfset := &nftables.Set{\n\t\tName:    setName,\n\t\tComment: input.set.Comment(),\n\t\tTable:   r.workTable,\n\t\t// required for prefixes\n\t\tInterval: true,\n\t\tKeyType:  r.af.setKeyType,\n\t}\n\n\telements := r.convertPrefixesToSet(prefixes)\n\tnElements := len(elements)\n\n\tmaxElements := maxPrefixesSet * 2\n\tinitialElements := elements[:min(maxElements, nElements)]\n\n\tif err := r.conn.AddSet(nfset, initialElements); err != nil {\n\t\treturn nil, fmt.Errorf(\"error adding set %s: %w\", setName, err)\n\t}\n\tif err := r.conn.Flush(); err != nil {\n\t\treturn nil, fmt.Errorf(\"flush error: %w\", err)\n\t}\n\tlog.Debugf(\"Created new ipset: %s with %d initial prefixes (total prefixes %d)\", setName, len(initialElements)/2, len(prefixes))\n\n\tvar subEnd int\n\tfor subStart := maxElements; subStart < nElements; subStart += maxElements {\n\t\tsubEnd = min(subStart+maxElements, nElements)\n\t\tsubElement := elements[subStart:subEnd]\n\t\tnSubPrefixes := len(subElement) / 2\n\t\tlog.Tracef(\"Adding new prefixes (%d) in ipset: %s\", nSubPrefixes, setName)\n\t\tif err := r.conn.SetAddElements(nfset, subElement); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"error adding prefixes (%d) to set %s: %w\", nSubPrefixes, setName, err)\n\t\t}\n\t\tif err := r.conn.Flush(); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"flush error: %w\", err)\n\t\t}","sourceCodeStart":544,"sourceCodeEnd":580,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/nftables/router_linux.go#L544-L580","documentation":"Returned by createIpSet (router_linux.go:561) when conn.AddSet fails while creating the interval set that backs a multi-prefix network. AddSet validates and queues the NEWSET message plus up to 3000 initial elements (maxPrefixesSet=1500 prefixes x 2 half-open interval endpoints, lines 558-559); construction-time failures include a nil Table, a KeyType whose byte length does not match the table family (r.af.setKeyType), or malformed set flags. Kernel rejections for the queued message surface one line later at Flush (error 683).","triggerScenarios":"Calling AddRouteFiltering/getIpSet with a firewall.Set whose hashed name collides with an incompatible leftover set, an IPv6 set created under an IPv4 router (or vice versa via familyForAddr mismatch), or an element key length that disagrees with KeyType during marshaling.","commonSituations":"Agent restart after an unclean shutdown leaving a set with the same hash name but different key type; dual-stack peers where the v4 and v6 routers build sets from the same prefix list; embedded/minimal kernels missing interval-set support (flags rejected).","solutions":["Confirm the set's KeyType matches the router's address family (4-byte keys for the ip table, 16-byte for ip6) — check r.af.setKeyType wiring.","If a stale set with the same HashedName exists from a previous run, delete the work table or DelSet it before re-adding (the manager recreates the table on init).","Verify set invariants the library requires: non-nil Table (r.workTable), Interval=true for prefixes, and a non-empty unique Name.","Check the wrapped error before Flush-related codes — if it is a marshaling/validation error it will reproduce deterministically, so fix construction instead of retrying."],"exampleFix":"// before\nnfset := &nftables.Set{Name: setName, Table: r.workTable, Interval: true, KeyType: r.af.setKeyType}\nif err := r.conn.AddSet(nfset, initialElements); err != nil {\n    return nil, fmt.Errorf(\"error adding set %s: %w\", setName, err)\n}\n\n// after\nnfset := &nftables.Set{Name: setName, Table: r.workTable, Interval: true, KeyType: r.af.setKeyType}\nif nfset.KeyType == 0 || nfset.KeyType.Length != r.af.addrLen {\n    return nil, fmt.Errorf(\"set %s key length %d does not match family %d\", setName, nfset.KeyType.Length, r.af.addrLen)\n}\nif err := r.conn.AddSet(nfset, initialElements); err != nil {\n    return nil, fmt.Errorf(\"error adding set %s: %w\", setName, err)\n}","handlingStrategy":"fallback","validationCode":"// Validate set construction matches the table family before AddSet\nwantLen := uint32(4)\nif r.af.tableFamily == nftables.TableFamilyIPv6 {\n    wantLen = 16\n}\nif nfset.Table == nil || nfset.KeyType.Length != wantLen || !nfset.Interval {\n    return nil, fmt.Errorf(\"invalid set definition %s: table=%v keyLen=%d interval=%v\", setName, nfset.Table, nfset.KeyType.Length, nfset.Interval)\n}","typeGuard":"func validSetForFamily(s *nftables.Set, family nftables.TableFamily) bool {\n\tif s == nil || s.Table == nil || !s.Interval {\n\t\treturn false\n\t}\n\twant := uint32(4)\n\tif family == nftables.TableFamilyIPv6 {\n\t\twant = 16\n\t}\n\treturn s.KeyType != nil && s.KeyType.Length == want\n}","tryCatchPattern":"if err := r.conn.AddSet(nfset, initialElements); err != nil {\n    // construction error: deterministic, do not retry blindly\n    if existing, gerr := r.conn.GetSetByName(r.workTable, setName); gerr == nil {\n        return existing, nil // fall back to the existing set\n    }\n    return nil, fmt.Errorf(\"error adding set %s: %w\", setName, err)\n}","preventionTips":["Assert set key length equals the router's address family length at creation time, in tests covering both families.","Recreate the netbird work table on agent start so leftover sets cannot collide with new definitions.","Unit-test set construction for v4 and v6 routers with the same prefix fixtures to catch family mix-ups.","Keep set names derived from content hashes (HashedName) so identical inputs always map to one set."],"tags":["go","nftables","netlink","ipset","firewall","linux"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}