{"record":{"id":"77304e46062d7b25","repo":"jdx/mise","slug":"firewall-rule-is-declared-more-than-once","errorCode":null,"errorMessage":"firewall rule '{}' is declared more than once","messagePattern":"firewall rule '(.+?)' is declared more than once","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"src/system/firewall.rs","lineNumber":320,"sourceCode":"    // more local scalar or same-named rule overrides its inherited value.\n    for cf in config.config_files.values().rev() {\n        if let Some(bootstrap) = cf.bootstrap_config()\n            && let Some(firewall) = bootstrap.linux.firewall\n        {\n            merged = Some(merge_toml_config(merged.unwrap_or_default(), firewall)?);\n        }\n    }\n    merged.map(FirewallRequest::from_toml).transpose()\n}\n\nfn merge_toml_config(\n    mut inherited: FirewallTomlConfig,\n    local: FirewallTomlConfig,\n) -> Result<FirewallTomlConfig> {\n    let mut local_names = HashSet::new();\n    for rule in &local.rules {\n        if !local_names.insert(&rule.name) {\n            bail!(\"firewall rule '{}' is declared more than once\", rule.name);\n        }\n    }\n    if local.backend.is_some() {\n        inherited.backend = local.backend;\n    }\n    if local.state.is_some() {\n        inherited.state = local.state;\n    }\n    if local.default_incoming.is_some() {\n        inherited.default_incoming = local.default_incoming;\n    }\n    if local.default_outgoing.is_some() {\n        inherited.default_outgoing = local.default_outgoing;\n    }\n    if local.exclusive.is_some() {\n        inherited.exclusive = local.exclusive;\n    }\n    if local.allow_lockout.is_some() {","sourceCodeStart":302,"sourceCodeEnd":338,"githubUrl":"https://github.com/jdx/mise/blob/9dcfcaa0dc8747a2577d3270b69bb9d8313b2807/src/system/firewall.rs#L302-L338","documentation":"Thrown while merging layered firewall config for `[bootstrap.linux.firewall]`: two rules in the same local mise.toml share one `name`. Rule names are the identity/merge key of the firewall ruleset (local rules override inherited ones by name), so duplicates inside one file are rejected during `merge_toml_config` before a request is ever built.","triggerScenarios":"Two `[[bootstrap.linux.firewall.rules]]` blocks in a single config file with the same `name = \"web\"` — typically after copy-pasting a rule block and forgetting to rename it.","commonSituations":"Copy-paste of rule blocks while iterating on config; merging hand-written snippets into one file; a rename that collides with an existing rule name.","solutions":["Rename one of the duplicates to a unique descriptive name (e.g. `web-http` and `web-https`).","Delete the stale copy if it was left by an aborted edit.","Remember names are merge keys across files: the same name in a local file intentionally overrides the inherited rule, but within one file names must be unique."],"exampleFix":"# before (mise.toml)\n[[bootstrap.linux.firewall.rules]]\nname = \"web\"\nport = 80\nprotocol = \"tcp\"\n\n[[bootstrap.linux.firewall.rules]]\nname = \"web\"        # duplicate\nport = 443\nprotocol = \"tcp\"\n\n# after\n[[bootstrap.linux.firewall.rules]]\nname = \"web-http\"\nport = 80\nprotocol = \"tcp\"\n\n[[bootstrap.linux.firewall.rules]]\nname = \"web-https\"\nport = 443\nprotocol = \"tcp\"","handlingStrategy":"validation","validationCode":"# pre-flight: unique rule names per file\npython3 - <<'PY'\nimport tomllib, collections\nfw = tomllib.load(open('mise.toml','rb')).get('bootstrap',{}).get('linux',{}).get('firewall',{})\ndupes = [n for n, c in collections.Counter(r['name'] for r in fw.get('rules',[])).items() if c > 1]\nif dupes: raise SystemExit(f\"duplicate firewall rule names: {dupes}\")\nPY","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Treat rule names as unique IDs; use descriptive suffixes (web-http, web-https).","After copy-pasting a rule block, rename before saving.","Lint config with `mise bootstrap firewall status` (parse-only)."],"tags":["mise","firewall","toml","duplicate-key","bootstrap","config"],"backgroundTag":"duplicate-config-key","analyzedSha":"9dcfcaa0dc8747a2577d3270b69bb9d8313b2807","analyzedAt":"2026-08-17T14:28:50.624Z","schemaVersion":2},"datasetVersion":"2026-08-21T13:17:26.733Z"}