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
- Write 'icmp' alone with no slash or port
- 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
- Document that ICMP types are not expressible in rule strings
- Strip trailing '/<digits>' when migrating ICMP rules from other firewall syntaxes
- Add UI dropdowns for protocol so free-text cannot combine icmp with a port
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
- invalid rule format: expected protocol/port or protocol/port
- empty port
- invalid duration format: %v
- no keys found in bundle
- failed to decode PEM data
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/8d3d98024b065c8a.
Report an issue: GitHub.