jdx/mise · error
firewall rule '{}' uses per-source connection limiting, whic
Error message
firewall rule '{}' uses per-source connection limiting, which firewalld policies cannot express safely; select backend = "nftables" or "ufw" What it means
Per-source connection limiting (`action = "limit"`) cannot be expressed safely through firewalld policies, so mise rejects any request that pairs the firewalld backend with a limit rule. The user must switch to the nftables or ufw backend, which can represent the limit semantics correctly.
Source
Thrown at src/system/firewall.rs:1052
}
FirewallBackend::Ufw => backend_active(backend),
FirewallBackend::Auto => false,
}
}
fn validate_backend_request(request: &FirewallRequest, backend: FirewallBackend) -> Result<()> {
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!(View on GitHub (pinned to afd2eddd3a)
Solutions
- Set `backend = "nftables"` or `backend = "ufw"` in the firewall request for hosts needing limit rules
- Install and enable the chosen backend on the host if missing
- Or restructure the rule to `action = "allow"`/`deny` under firewalld and implement rate limiting with a separate rich rule/nft set outside mise
Example fix
// before backend = "firewalld" [[rule]] name = "ssh-limit" action = "limit" direction = "incoming" protocol = "tcp" // after backend = "nftables" [[rule]] name = "ssh-limit" action = "limit" direction = "incoming" protocol = "tcp"
Defensive patterns
Strategy: validation
Validate before calling
// config lint
function backendSupportsLimit(backend, rules) {
return backend !== "firewalld" || !rules.some(r => r.action === "limit");
} Prevention
- Standardize on nftables or ufw wherever rate-limit rules are needed
- Split per-host configs: firewalld hosts get allow/deny-only rulesets
- Check `mise bootstrap firewall status` for the detected backend before authoring rules
- Document that action=limit is incompatible with firewalld in your team's firewall README
When it happens
Trigger: A firewall request where `backend = "firewalld"` (explicitly or via auto-detection on a firewalld host) and at least one rule has `action = "limit"`, passed through `validate_backend_request()` during inspect/apply.
Common situations: Running on RHEL/CentOS/Fedora where firewalld is the detected backend, while the ruleset was written with ufw-style rate-limit rules; sharing one bootstrap config across Debian (ufw) and RHEL (firewalld) 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
- firewall rule '{}' uses interface matching, which firewalld
- refusing firewall default incoming {} over SSH: blocking rul
- firewall rule '{}' uses action = "limit", which requires dir
- firewall rule '{}' uses protocol {}, which UFW does not supp
- firewall port '{range}' must be a number or inclusive range
AI-assisted analysis of jdx/mise@afd2eddd3a (2026-09-09).
Data as JSON: /api/errors/ede978a99f082bc3.
Report an issue: GitHub.