jdx/mise · error

firewall rule '{}' is declared more than once

Error message

firewall rule '{}' is declared more than once

What it means

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.

Source

Thrown at src/system/firewall.rs:320

    // more local scalar or same-named rule overrides its inherited value.
    for cf in config.config_files.values().rev() {
        if let Some(bootstrap) = cf.bootstrap_config()
            && let Some(firewall) = bootstrap.linux.firewall
        {
            merged = Some(merge_toml_config(merged.unwrap_or_default(), firewall)?);
        }
    }
    merged.map(FirewallRequest::from_toml).transpose()
}

fn merge_toml_config(
    mut inherited: FirewallTomlConfig,
    local: FirewallTomlConfig,
) -> Result<FirewallTomlConfig> {
    let mut local_names = HashSet::new();
    for rule in &local.rules {
        if !local_names.insert(&rule.name) {
            bail!("firewall rule '{}' is declared more than once", rule.name);
        }
    }
    if local.backend.is_some() {
        inherited.backend = local.backend;
    }
    if local.state.is_some() {
        inherited.state = local.state;
    }
    if local.default_incoming.is_some() {
        inherited.default_incoming = local.default_incoming;
    }
    if local.default_outgoing.is_some() {
        inherited.default_outgoing = local.default_outgoing;
    }
    if local.exclusive.is_some() {
        inherited.exclusive = local.exclusive;
    }
    if local.allow_lockout.is_some() {

View on GitHub (pinned to 9dcfcaa0dc)

Solutions

  1. Rename one of the duplicates to a unique descriptive name (e.g. `web-http` and `web-https`).
  2. Delete the stale copy if it was left by an aborted edit.
  3. 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.

Example fix

# before (mise.toml)
[[bootstrap.linux.firewall.rules]]
name = "web"
port = 80
protocol = "tcp"

[[bootstrap.linux.firewall.rules]]
name = "web"        # duplicate
port = 443
protocol = "tcp"

# after
[[bootstrap.linux.firewall.rules]]
name = "web-http"
port = 80
protocol = "tcp"

[[bootstrap.linux.firewall.rules]]
name = "web-https"
port = 443
protocol = "tcp"
Defensive patterns

Strategy: validation

Validate before calling

# pre-flight: unique rule names per file
python3 - <<'PY'
import tomllib, collections
fw = tomllib.load(open('mise.toml','rb')).get('bootstrap',{}).get('linux',{}).get('firewall',{})
dupes = [n for n, c in collections.Counter(r['name'] for r in fw.get('rules',[])).items() if c > 1]
if dupes: raise SystemExit(f"duplicate firewall rule names: {dupes}")
PY

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jdx/mise@9dcfcaa0dc (2026-08-17). Data as JSON: /api/errors/77304e46062d7b25. Report an issue: GitHub.