{"record":{"id":"43a881f018c5224d","repo":"netbirdio/netbird","slug":"invalid-translated-port-v-43a881","errorCode":null,"errorMessage":"invalid translated port: %v","messagePattern":"invalid translated port: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"client/firewall/nftables/router_linux.go","lineNumber":1668,"sourceCode":"\t\tExprs:    dnatExprs,\n\t\tUserData: []byte(ruleKey + dnatSuffix),\n\t}\n\tr.conn.AddRule(dnatRule)\n\tr.rules[ruleKey+dnatSuffix] = dnatRule\n\n\treturn nil\n}\n\nfunc (r *router) handleTranslatedPort(rule firewall.ForwardRule) ([]expr.Any, uint32, uint32, error) {\n\tswitch {\n\tcase rule.TranslatedPort.IsRange && len(rule.TranslatedPort.Values) == 2:\n\t\treturn r.handlePortRange(rule)\n\tcase len(rule.TranslatedPort.Values) == 0:\n\t\treturn r.handleAddressOnly(rule)\n\tcase len(rule.TranslatedPort.Values) == 1:\n\t\treturn r.handleSinglePort(rule)\n\tdefault:\n\t\treturn nil, 0, 0, fmt.Errorf(\"invalid translated port: %v\", rule.TranslatedPort)\n\t}\n}\n\nfunc (r *router) handlePortRange(rule firewall.ForwardRule) ([]expr.Any, uint32, uint32, error) {\n\texprs := []expr.Any{\n\t\t&expr.Immediate{\n\t\t\tRegister: 1,\n\t\t\tData:     rule.TranslatedAddress.AsSlice(),\n\t\t},\n\t\t&expr.Immediate{\n\t\t\tRegister: 2,\n\t\t\tData:     binaryutil.BigEndian.PutUint16(rule.TranslatedPort.Values[0]),\n\t\t},\n\t\t&expr.Immediate{\n\t\t\tRegister: 3,\n\t\t\tData:     binaryutil.BigEndian.PutUint16(rule.TranslatedPort.Values[1]),\n\t\t},\n\t}","sourceCodeStart":1650,"sourceCodeEnd":1686,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/firewall/nftables/router_linux.go#L1650-L1686","documentation":"handleTranslatedPort dispatches on rule.TranslatedPort: two values with IsRange map to a range, zero values to address-only DNAT, one value to a single port. Any other shape (three or more values, or IsRange with one value) falls to default and returns 'invalid translated port' printing the whole Port struct. It is a deterministic validation error raised while building expressions, before any netlink message is queued.","triggerScenarios":"A ForwardRule whose TranslatedPort.Values has length 3 or more, or IsRange=true with a single value, reaches addDnatRedirect: hand-built rules or a management payload that filled several ports without setting IsRange.","commonSituations":"Port-forwarding APIs that forward a list of ports to one translated port; version skew introducing new port shapes; test fixtures writing Port{Values: []uint16{80, 8080}} and forgetting IsRange.","solutions":["Validate the TranslatedPort shape before building rules: exactly 0, 1, or (IsRange with exactly 2) values.","Map many ports to one translated port by emitting one ForwardRule per port, not one rule with 3+ values.","Always set IsRange=true when supplying two boundary ports.","Print the rule's Port struct (the %v payload shows IsRange/Values) to find the misbehaving producer."],"exampleFix":"// before: two ports without IsRange -> default case -> error\nrule.TranslatedPort = firewall.Port{Values: []uint16{8080, 8443}}\n\n// after: either a proper range\nrule.TranslatedPort = firewall.Port{IsRange: true, Values: []uint16{8080, 8443}}\n// or one rule per port\nruleA.TranslatedPort = firewall.Port{Values: []uint16{8080}}\nruleB.TranslatedPort = firewall.Port{Values: []uint16{8443}}","handlingStrategy":"validation","validationCode":"func validTranslatedPort(p firewall.Port) bool {\n    switch {\n    case len(p.Values) == 0:\n        return true // address-only DNAT\n    case len(p.Values) == 1:\n        return true\n    case p.IsRange && len(p.Values) == 2:\n        return p.Values[0] <= p.Values[1]\n    }\n    return false\n}\n\n// use before creating forward rules\nif !validTranslatedPort(rule.TranslatedPort) {\n    return fmt.Errorf(\"invalid translated port shape: %+v\", rule.TranslatedPort)\n}","typeGuard":"func isRangePort(p firewall.Port) bool {\n    return p.IsRange && len(p.Values) == 2 && p.Values[0] <= p.Values[1]\n}","tryCatchPattern":"if _, _, _, err := r.handleTranslatedPort(rule); err != nil {\n    // deterministic config error: fix the producer, do not retry\n    return fmt.Errorf(\"rejecting forward rule with malformed translated port %+v: %w\", rule.TranslatedPort, err)\n}","preventionTips":["Constrain port-forwarding config schemas to 0, 1, or exactly 2 boundary ports with an explicit range flag.","Emit one rule per port when mapping multiple ports to one target.","Validate port shapes in management/CLI code so the firewall backend never sees them."],"tags":["validation","port-range","port-forwarding"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}