slackhq/nebula · error

%s rule #%v; cidr did not parse; %s

Error message

%s rule #%v; cidr did not parse; %s

What it means

AddFirewallRulesFromConfig validates each rule's cidr with netip.ParsePrefix unless the value is empty or "any". A malformed CIDR (missing prefix length, bad IP, invalid mask) produces this wrapped error naming the table, rule index, and parse failure.

Source

Thrown at firewall.go:390

			startPort, endPort, err = parsePort(sPort)
		case "icmp":
			proto = iputil.IPProtocolICMP
			startPort = firewall.PortAny
			endPort = firewall.PortAny
			if sPort != "" {
				l.Warn("ignoring port specification for ICMP firewall rule", "port", sPort)
			}
		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,
			)
		}

View on GitHub (pinned to dd8f660c0a)

Solutions

  1. Provide a valid CIDR prefix, e.g. "10.0.0.0/24"; use "/32" for a single IPv4 host.
  2. Use "any" as the value if the rule should match any remote CIDR.
  3. Validate locally with netip.ParsePrefix (or an online CIDR checker) before deploying the config.

Example fix

// before (config)
- cidr: 10.0.0.0
  proto: any
// after
- cidr: 10.0.0.0/24
  proto: any
Defensive patterns

Strategy: validation

Validate before calling

import "netip"

func validateCidrField(rules []map[string]any, key string) error {
    for i, r := range rules {
        v, _ := r[key].(string)
        if v == "" || v == "any" { continue }
        if _, err := netip.ParsePrefix(v); err != nil {
            return fmt.Errorf("rule #%d: %s %q is not a valid CIDR: %v", i, key, v, err)
        }
    }
    return nil
}

Try / catch

if err := fw.AddFirewallRulesFromConfig(l, "inbound", rules); err != nil {
    if strings.Contains(err.Error(), "cidr did not parse") {
        log.Fatalf("fix CIDR (include /prefix length): %v", err)
    }
    return err
}

Prevention

When it happens

Trigger: A rule with cidr like "10.0.0.0" (missing /prefix), "10.0.0.0/33", "hostnames don't work", or an IPv6/IPv4 mismatch, and not "any".

Common situations: Omitting the prefix length out of habit, using a hostname or IP list instead of a single CIDR, or writing single-host IPs without /32.

Related errors


AI-assisted analysis of slackhq/nebula@dd8f660c0a (2026-09-03). Data as JSON: /api/errors/f0cf4f79f64bae7e. Report an issue: GitHub.