jdx/mise · error

firewall rule ' ' uses interface matching, which firewalld…

Error message

firewall rule '{}' uses interface matching, which firewalld policies cannot express safely; select backend = "nftables" or "ufw"

What it means

Interface matching (binding a rule to a specific network interface, e.g. `interface = "eth0"`) cannot be expressed safely in firewalld policies as mise models them. Requests that combine the firewalld backend with a rule that sets `interface` are rejected up front to avoid rules that silently behave differently than declared.

Solutions

  1. Switch to `backend = "nftables"` or `backend = "ufw"`, which support interface matching
  2. Or remove the `interface` field and rely on source CIDR restrictions to scope the rule
  3. Or model interface scoping via firewalld zones manually and keep that rule out of the mise-managed request

Example fix

// before
backend = "firewalld"
[[rule]]
name = "ssh-internal"
interface = "eth0"
// after
backend = "firewalld"
[[rule]]
name = "ssh-internal"
from = "10.0.0.0/8"  # scope by source instead of interface
Defensive patterns

Strategy: validation

Validate before calling

// config lint
function backendSupportsInterface(backend, rules) {
  return backend !== "firewalld" || !rules.some(r => r.interface);
}

Prevention

When it happens

Trigger: A firewall request with `backend = "firewalld"` containing any rule whose `interface` field is `Some(...)` (non-empty), validated in `validate_backend_request()` before apply.

Common situations: Rules authored for a ufw/nftables host (where per-interface binding works) applied to a firewalld-based machine; trying to scope SSH access to one NIC on a RHEL host; config templated with interface names across heterogeneous hosts.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09). Data as JSON: /api/errors/d5c84fc7d2c94ded. Report an issue: GitHub.

Appendix: source

Thrown at src/system/firewall.rs:1059

    for rule in &request.rules {
        if rule.action == FirewallAction::Limit {
            if rule.direction != FirewallDirection::Incoming
                || rule.protocol != Some(FirewallProtocol::Tcp)
            {
                bail!(
                    "firewall rule '{}' uses action = \"limit\", which requires direction = \"incoming\" and protocol = \"tcp\"",
                    rule.name
                );
            }
            if backend == FirewallBackend::Firewalld {
                bail!(
                    "firewall rule '{}' uses per-source connection limiting, which firewalld policies cannot express safely; select backend = \"nftables\" or \"ufw\"",
                    rule.name
                );
            }
        }
        if backend == FirewallBackend::Firewalld && rule.interface.is_some() {
            bail!(
                "firewall rule '{}' uses interface matching, which firewalld policies cannot express safely; select backend = \"nftables\" or \"ufw\"",
                rule.name
            );
        }
        if backend == FirewallBackend::Ufw
            && matches!(
                rule.protocol,
                Some(FirewallProtocol::Sctp | FirewallProtocol::Dccp)
            )
        {
            bail!(
                "firewall rule '{}' uses protocol {}, which UFW does not support; select backend = \"nftables\" or \"firewalld\"",
                rule.name,
                rule.protocol.expect("matched protocol").as_str()
            );
        }
    }
    Ok(())

View on GitHub (pinned to afd2eddd3a)