{"record":{"id":"47b531058e29276a","repo":"jdx/mise","slug":"firewall-port-range-must-be-a-number-or-inclus","errorCode":null,"errorMessage":"firewall port '{range}' must be a number or inclusive range","messagePattern":"firewall port '(.+?)' must be a number or inclusive range","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/firewall.rs","lineNumber":190,"sourceCode":"#[serde(untagged)]\npub enum FirewallPortToml {\n    Single(u16),\n    Range(String),\n}\n\n#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]\npub struct FirewallPort {\n    start: u16,\n    end: u16,\n}\n\nimpl FirewallPort {\n    fn from_toml(value: FirewallPortToml) -> Result<Self> {\n        let (start, end) = match value {\n            FirewallPortToml::Single(port) => (port, port),\n            FirewallPortToml::Range(range) => {\n                let Some((start, end)) = range.split_once(['-', ':']) else {\n                    bail!(\"firewall port '{range}' must be a number or inclusive range\")\n                };\n                (start.parse()?, end.parse()?)\n            }\n        };\n        if start == 0 || end == 0 || start > end {\n            bail!(\"firewall port range {start}-{end} is invalid\");\n        }\n        Ok(Self { start, end })\n    }\n\n    fn contains(self, port: u16) -> bool {\n        self.start <= port && port <= self.end\n    }\n\n    fn render(self, separator: char) -> String {\n        if self.start == self.end {\n            self.start.to_string()\n        } else {","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/firewall.rs#L172-L208","documentation":"Raised while parsing a `[bootstrap.linux.firewall]` rule's `port` key. The key is an untagged TOML value: either a bare integer (single port) or a string containing an inclusive range with a `-` or `:` separator (\"8000-9000\", \"8000:9000\"). This error means a string was supplied but contained no range separator, so it cannot be split into start/end — almost always a single port that was quoted.","triggerScenarios":"`port = \"443\"` in a rule: the untagged enum first tries `Single(u16)` and fails because the value is a TOML string, then `Range(\"443\")` fails `split_once(['-', ':'])`. Also triggered by free-form strings like \"https\", \"443,\" or \"443 8443\" (comma/space lists are unsupported).","commonSituations":"Quoting numbers out of TOML habit; copying port strings from docker/ufw documentation that uses \"443\" or \"443,8443\" forms; YAML-to-TOML migrations that stringified values.","solutions":["Use a bare integer for a single port: `port = 443` (remember `protocol = \"tcp\"` is required when port is set).","Use an inclusive range string: `port = \"8000-9000\"` or `port = \"8000:9000\"`.","List each port in its own `[[bootstrap.linux.firewall.rules]]` entry — comma lists are not supported.","Validate config cheaply with `mise bootstrap firewall status` (it parses the config without applying) before `apply`."],"exampleFix":"# before (mise.toml)\n[[bootstrap.linux.firewall.rules]]\nname = \"https\"\nport = \"443\"\n\n# after\n[[bootstrap.linux.firewall.rules]]\nname = \"https\"\nport = 443\nprotocol = \"tcp\"\n# or a range: port = \"8000-9000\", protocol = \"tcp\"","handlingStrategy":"validation","validationCode":"# pre-flight: quoted single ports and separator-less strings\npython3 - <<'PY'\nimport tomllib\nfw = tomllib.load(open('mise.toml','rb')).get('bootstrap',{}).get('linux',{}).get('firewall',{})\nfor r in fw.get('rules',[]):\n    p = r.get('port')\n    if isinstance(p, str) and not any(c in p for c in '-:'):\n        raise SystemExit(f\"rule {r['name']}: port string '{p}' has no range separator; use an integer\")\nPY","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Never quote single ports; TOML integers are valid.","Use only 'start-end' or 'start:end' for ranges; comma lists are unsupported.","Run `mise bootstrap firewall status` after editing config — it parses without applying."],"tags":["mise","firewall","toml","port-range","bootstrap","config"],"backgroundTag":"invalid-port-range","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}