slackhq/nebula · error
%s rule #%v; local_cidr did not parse; %s
Error message
%s rule #%v; local_cidr did not parse; %s
What it means
Identical to the cidr check, AddFirewallRulesFromConfig validates each rule's local_cidr with netip.ParsePrefix unless it is empty or "any". local_cidr constrains the destination address inside the tunnel, so it must be a valid IP prefix.
Source
Thrown at firewall.go:397
}
default:
return fmt.Errorf("%s rule #%v; proto was not understood; `%s`", table, i, r.Proto)
}
if err != nil {
return fmt.Errorf("%s rule #%v; %s %s", table, i, errPort, err)
}
if r.Cidr != "" && r.Cidr != "any" {
_, err = netip.ParsePrefix(r.Cidr)
if err != nil {
return fmt.Errorf("%s rule #%v; cidr did not parse; %s", table, i, err)
}
}
if r.LocalCidr != "" && r.LocalCidr != "any" {
_, err = netip.ParsePrefix(r.LocalCidr)
if err != nil {
return fmt.Errorf("%s rule #%v; local_cidr did not parse; %s", table, i, err)
}
}
if warning := r.sanity(); warning != nil {
l.Warn("firewall rule sanity check",
"table", table,
"rule", i,
"warning", warning,
)
}
err = fw.AddRule(inbound, proto, startPort, endPort, r.Groups, r.Host, r.Cidr, r.LocalCidr, r.CAName, r.CASha)
if err != nil {
return fmt.Errorf("%s rule #%v; `%s`", table, i, err)
}
}
return nilView on GitHub (pinned to dd8f660c0a)
Solutions
- Provide a valid CIDR prefix for local_cidr (e.g. "192.168.1.0/24").
- Use "any" if the rule should match any local destination.
- Confirm the value is a prefix (IP + /mask), not a bare IP or hostname.
Example fix
// before (config) - local_cidr: 192.168.1.0 port: 22 proto: tcp group: admins // after - local_cidr: 192.168.1.0/24 port: 22 proto: tcp group: admins
Defensive patterns
Strategy: validation
Validate before calling
import "netip"
func validateLocalCidr(rules []map[string]any) error {
for i, r := range rules {
v, _ := r["local_cidr"].(string)
if v == "" || v == "any" { continue }
if _, err := netip.ParsePrefix(v); err != nil {
return fmt.Errorf("rule #%d: local_cidr %q invalid: %v", i, v, err)
}
}
return nil
} Try / catch
if err := fw.AddFirewallRulesFromConfig(l, "inbound", rules); err != nil {
if strings.Contains(err.Error(), "local_cidr did not parse") {
log.Fatalf("local_cidr must be a CIDR prefix or 'any': %v", err)
}
return err
} Prevention
- Remember local_cidr is the tunneled destination prefix — always include /mask.
- Don't confuse local_cidr with the host's tunl/unsafe_routes cidr syntax.
- Validate both cidr and local_cidr with netip.ParsePrefix in CI config tests.
When it happens
Trigger: A rule with local_cidr like "192.168.1.0" (missing /prefix), "0.0.0.0/0/0", or other malformed prefix strings, and not "any".
Common situations: Copy-paste errors when configuring unsafe_routes/routed ranges, forgetting the prefix length, or confusing local_cidr with the host.cidr format.
Related errors
- %s rule #%v; cidr did not parse; %s
- ErrInvalidLocalIP
- unknown protocol %v
- %s failed to parse, should be an array of rules
- %s rule #%v; %s
AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03).
Data as JSON: /api/errors/25e9377e6ccd0c8b.
Report an issue: GitHub.