{"record":{"id":"bc8d80f53a69360f","repo":"tailscale/tailscale","slug":"add-match-subnet-route-mark-rule-v4-w","errorCode":null,"errorMessage":"add match subnet route mark rule v4: %w","messagePattern":"add match subnet route mark rule v4: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"util/linuxfw/nftables_runner.go","lineNumber":1742,"sourceCode":"\tinputChain, err := getChainFromTable(conn, n.nft4.Filter, chainNameInput)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get input chain v4: %v\", err)\n\t}\n\tif err = addAcceptIncomingPacketRule(conn, n.nft4.Filter, inputChain, tunname); err != nil {\n\t\treturn fmt.Errorf(\"add accept incoming packet rule v4: %w\", err)\n\t}\n\n\tforwardChain, err := getChainFromTable(conn, n.nft4.Filter, chainNameForward)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"get forward chain v4: %v\", err)\n\t}\n\n\tif err = addSetSubnetRouteMarkRule(conn, n.nft4.Filter, forwardChain, tunname); err != nil {\n\t\treturn fmt.Errorf(\"add set subnet route mark rule v4: %w\", err)\n\t}\n\n\tif err = addMatchSubnetRouteMarkRule(conn, n.nft4.Filter, forwardChain, Accept); err != nil {\n\t\treturn fmt.Errorf(\"add match subnet route mark rule v4: %w\", err)\n\t}\n\n\tif err = addDropOutgoingPacketFromCGNATRangeRuleWithTunname(conn, n.nft4.Filter, forwardChain, tunname); err != nil {\n\t\treturn fmt.Errorf(\"add drop outgoing packet from cgnat range rule v4: %w\", err)\n\t}\n\n\tif err = addAcceptOutgoingPacketRule(conn, n.nft4.Filter, forwardChain, tunname); err != nil {\n\t\treturn fmt.Errorf(\"add accept outgoing packet rule v4: %w\", err)\n\t}\n\n\tif err = conn.Flush(); err != nil {\n\t\treturn fmt.Errorf(\"flush base v4: %w\", err)\n\t}\n\n\treturn nil\n}\n\n// addBase6 adds some basic IPv6 processing rules.","sourceCodeStart":1724,"sourceCodeEnd":1760,"githubUrl":"https://github.com/tailscale/tailscale/blob/6e0912f97994f927632b34ae9e63b53d6516a6ac/util/linuxfw/nftables_runner.go#L1724-L1760","documentation":"addBase4 failed to install the mark-match accept rule into IPv4 ts-forward. The rule matches packets whose mark, masked with the Tailscale fwmark mask, equals the subnet-route mark, then accepts them; construction (createMatchSubnetRouteMarkRule) cannot fail, so the wrapped error is the helper's conn.Flush() netlink commit error.","triggerScenarios":"EPERM at commit without CAP_NET_ADMIN; ENOENT when ts-forward/filter was flushed concurrently; EOPNOTSUPP/EINVAL on kernels lacking the needed nft expressions; closed nftables.Conn.","commonSituations":"Same family as the other base-rule flush failures: restricted containers, unsupported kernels, racing firewall managers.","solutions":["Verify CAP_NET_ADMIN and retry after AddChains() on ENOENT","Classify errno and switch firewall mode on EOPNOTSUPP","Remove concurrent ruleset flushes","Check Conn lifecycle"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// same pre-flight as the other flush failures: probe + re-ensure chains\nconn, err := nftables.New()\nif err != nil { return err }\ndefer conn.Close()\nif _, err := conn.ListTables(); err != nil { return err }\nif err := fw.AddChains(); err != nil { return err }","typeGuard":"func isFlushCommitErr(err error) bool {\n\treturn errors.Is(err, unix.EPERM) || errors.Is(err, unix.ENOENT) ||\n\t\terrors.Is(err, unix.EOPNOTSUPP) || errors.Is(err, unix.ENOTSUPP)\n}","tryCatchPattern":"if err := fw.AddBase(tun); err != nil {\n\tif errors.Is(err, unix.ENOENT) {\n\t\tif fw.AddChains() == nil {\n\t\t\treturn fw.AddBase(tun)\n\t\t}\n\t}\n\treturn err\n}","preventionTips":["Do not drop capabilities between adding rules in one AddBase call","Retry once after AddChains on ENOENT races","Verify the final chain contents after any retry to catch duplicated rules","Serialize firewall mutation with external tooling"],"tags":["nftables","netlink","firewall","linux","go","tailscale","fwmark"],"backgroundTag":"nftables-flush-failed","analyzedSha":"6e0912f97994f927632b34ae9e63b53d6516a6ac","analyzedAt":"2026-08-18T08:17:25.280Z","contentChangedAt":"2026-08-18T08:17:25.280Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}