netbirdio/netbird · error

icmp does not accept ports; use 'icmp' without '/…'

Error message

icmp does not accept ports; use 'icmp' without '/…'

What it means

ParseRuleString rejects 'icmp/<anything>' because ICMP has no port concept in this model; the protocol must appear bare. The error fires specifically when the protocol segment is 'icmp' and a '/'-separated port part is also present.

Source

Thrown at shared/management/types/policy.go:212

		return PolicyRuleProtocolICMP, RulePortRange{}, nil
	}

	split := strings.Split(rule, "/")
	if len(split) != 2 {
		return "", RulePortRange{}, errors.New("invalid rule format: expected protocol/port or protocol/port-range")
	}

	protoStr := strings.TrimSpace(split[0])
	portStr := strings.TrimSpace(split[1])

	var protocol PolicyRuleProtocolType
	switch protoStr {
	case "tcp":
		protocol = PolicyRuleProtocolTCP
	case "udp":
		protocol = PolicyRuleProtocolUDP
	case "icmp":
		return "", RulePortRange{}, errors.New("icmp does not accept ports; use 'icmp' without '/…'")
	case "netbird-ssh":
		return PolicyRuleProtocolNetbirdSSH, RulePortRange{Start: nativeSSHPortNumber, End: nativeSSHPortNumber}, nil
	default:
		return "", RulePortRange{}, fmt.Errorf("invalid protocol: %q", protoStr)
	}

	portRange, err := parsePortRange(portStr)
	if err != nil {
		return "", RulePortRange{}, err
	}

	return protocol, portRange, nil
}

func parsePortRange(portStr string) (RulePortRange, error) {
	if strings.Contains(portStr, "-") {
		rangeParts := strings.Split(portStr, "-")
		if len(rangeParts) != 2 {

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Write 'icmp' alone with no slash or port
  2. Express ICMP type filtering outside this parser — it does not model ICMP types

Example fix

// before
proto, ports, err := types.ParseRuleString("icmp/8")

// after
proto, ports, err := types.ParseRuleString("icmp")
Defensive patterns

Strategy: validation

Validate before calling

func normalizeRule(rule string) (string, error) {
	r := strings.ToLower(strings.TrimSpace(rule))
	if strings.HasPrefix(r, "icmp/") {
		return "", fmt.Errorf("icmp rule %q must not carry a port; use 'icmp'", rule)
	}
	return r, nil
}

Type guard

func isBareIcmpRule(rule string) bool {
	return strings.ToLower(strings.TrimSpace(rule)) == "icmp"
}

Try / catch

if _, _, err := types.ParseRuleString(rule); err != nil {
	if strings.Contains(err.Error(), "icmp does not accept ports") {
		rule = "icmp" // strip the misplaced type code and retry
	}
}

Prevention

When it happens

Trigger: Rules like icmp/8, icmp/echo-request, or icmp/0 — usually ICMP type codes written where a port would go.

Common situations: Porting firewall rules from tools that number ICMP types/messages; copy-pasting a tcp rule and swapping only the protocol word.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/8d3d98024b065c8a. Report an issue: GitHub.