{"record":{"id":"181d6de6ffe149dc","repo":"slackhq/nebula","slug":"start-port-was-lower-than-end-port","errorCode":null,"errorMessage":"start port was lower than end port","messagePattern":"start port was lower than end port","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"firewall.go","lineNumber":658,"sourceCode":"\t\tif ft.TCP.match(p, incoming, c, caPool) {\n\t\t\treturn true\n\t\t}\n\tcase iputil.IPProtocolUDP:\n\t\tif ft.UDP.match(p, incoming, c, caPool) {\n\t\t\treturn true\n\t\t}\n\tcase iputil.IPProtocolICMP, iputil.IPProtocolICMPv6:\n\t\tif ft.ICMP.match(p, incoming, c, caPool) {\n\t\t\treturn true\n\t\t}\n\t}\n\n\treturn false\n}\n\nfunc (fp firewallPort) addRule(f *Firewall, startPort int32, endPort int32, groups []string, host string, cidr, localCidr, caName string, caSha string) error {\n\tif startPort > endPort {\n\t\treturn fmt.Errorf(\"start port was lower than end port\")\n\t}\n\n\tfor i := startPort; i <= endPort; i++ {\n\t\tif _, ok := fp[i]; !ok {\n\t\t\tfp[i] = &FirewallCA{\n\t\t\t\tCANames: make(map[string]*FirewallRule),\n\t\t\t\tCAShas:  make(map[string]*FirewallRule),\n\t\t\t}\n\t\t}\n\n\t\tif err := fp[i].addRule(f, groups, host, cidr, localCidr, caName, caSha); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\n\treturn nil\n}\n","sourceCodeStart":640,"sourceCodeEnd":676,"githubUrl":"https://github.com/slackhq/nebula/blob/dd8f660c0ac37903ec4080ca4d3c861ba9342ceb/firewall.go#L640-L676","documentation":"firewallPort.addRule rejects any rule where startPort > endPort. Ranges must be ascending and inclusive; a descending range would install zero rules silently, so the library fails fast instead. The error is usually wrapped by AddFirewallRulesFromConfig with the table and rule index.","triggerScenarios":"fw.AddRule (via firewallPort.addRule) called with startPort > endPort, e.g. port range '100-50' from config, or a programmatic AddRule call with swapped arguments.","commonSituations":"Typo'd YAML port ranges written high-to-low; copy-pasted ranges with values swapped; code that computes min/max in the wrong order.","solutions":["Swap the range so start <= end (port: '50-100')","If using config, reorder the range values in the port field","If calling AddRule programmatically, sort the ports before passing them"],"exampleFix":"// before\nfw.AddRule(true, proto, 8080, 80, ...)\n// after\nfw.AddRule(true, proto, 80, 8080, ...)","handlingStrategy":"validation","validationCode":"func checkPorts(start, end int32) error {\n    if start > end {\n        return fmt.Errorf(\"start port %d is greater than end port %d\", start, end)\n    }\n    return nil\n}","typeGuard":"func ascendingRange(start, end int32) (int32, int32, bool) {\n    if start <= end { return start, end, true }\n    return end, start, false // false signals the caller had them swapped\n}","tryCatchPattern":"if err := fw.AddRule(inbound, proto, start, end, ...); err != nil {\n    if strings.Contains(err.Error(), \"start port was lower than end port\") {\n        start, end = end, start // or surface a config bug\n    }\n    return err\n}","preventionTips":["Normalize ranges with min/max before calling AddRule","Lint config port fields for inverted ranges","Unit-test any code that computes port ranges from user input"],"tags":["go","firewall","port-range","validation"],"backgroundTag":"firewall-rule-invalid","analyzedSha":"dd8f660c0ac37903ec4080ca4d3c861ba9342ceb","analyzedAt":"2026-09-03T11:13:55.444Z","contentChangedAt":"2026-09-03T11:13:55.444Z","schemaVersion":2},"datasetVersion":"2026-09-10T17:17:09.494Z"}