netbirdio/netbird · error
invalid protocol: %w
Error message
invalid protocol: %w
What it means
Returned by applyRouteACL when convertToFirewallProtocol hits its default branch: the proto RuleProtocol value is outside {TCP, UDP, ICMP, ALL} known to this agent build. Note the function still returns ProtocolALL alongside the error, but the caller discards the rule, and because the ACL default posture is deny, the route's traffic is not permitted by this rule. New enum values are exactly how a newer management breaks an older agent here.
Source
Thrown at client/internal/acl/manager.go:260
}
var sources []netip.Prefix
for _, sourceRange := range rule.SourceRanges {
source, err := netip.ParsePrefix(sourceRange)
if err != nil {
return "", fmt.Errorf("parse source range: %w", err)
}
sources = append(sources, source)
}
destination, err := determineDestination(rule, dynamicResolver, sources)
if err != nil {
return "", fmt.Errorf("determine destination: %w", err)
}
protocol, err := convertToFirewallProtocol(rule.Protocol)
if err != nil {
return "", fmt.Errorf("invalid protocol: %w", err)
}
action, err := convertFirewallAction(rule.Action)
if err != nil {
return "", fmt.Errorf("invalid action: %w", err)
}
dPorts := convertPortInfo(rule.PortInfo)
addedRule, err := d.firewall.AddRouteFiltering(rule.PolicyID, sources, destination, protocol, nil, dPorts, action)
if err != nil {
return "", fmt.Errorf("add route rule: %w", err)
}
return id.RuleID(addedRule.ID()), nil
}
func (d *DefaultManager) protoRuleToFirewallRule(View on GitHub (pinned to 93e97f4bf1)
Solutions
- Update the agent to at least the version of management in use so the enum coverage matches
- Set a concrete protocol (tcp/udp/icmp/all) on the affected network route policy
- If rolling updates take time, remove the offending policy for the lagging agents so their route rules apply cleanly
Defensive patterns
Strategy: type-guard
Validate before calling
// whitelist check before dispatching a rule to agents
var knownProtocols = map[mgmProto.RuleProtocol]bool{
mgmProto.RuleProtocol_TCP: true,
mgmProto.RuleProtocol_UDP: true,
mgmProto.RuleProtocol_ICMP: true,
mgmProto.RuleProtocol_ALL: true,
}
func protocolSupportedByAgents(p mgmProto.RuleProtocol) bool {
return knownProtocols[p]
} Type guard
func isKnownProtocol(p mgmProto.RuleProtocol) bool {
switch p {
case mgmProto.RuleProtocol_TCP, mgmProto.RuleProtocol_UDP,
mgmProto.RuleProtocol_ICMP, mgmProto.RuleProtocol_ALL:
return true
}
return false
} Try / catch
protocol, err := convertToFirewallProtocol(rule.Protocol)
if err != nil {
if strings.Contains(err.Error(), "invalid protocol type") {
log.Warnf("management sent unknown protocol %d - agent older than management? rule skipped", rule.Protocol)
}
return "", fmt.Errorf("invalid protocol: %w", err)
} Prevention
- Upgrade agents before (or together with) management so new protocol enums are understood
- Always set an explicit protocol on network route policies; never rely on the zero value
- On mixed fleets, avoid new protocol values in policies until the oldest agent supports them
When it happens
Trigger: Management newer than the agent emitting a RuleProtocol the old agent's switch does not know; RuleProtocol_UNKNOWN/unset (0) reaching route ACLs from unvalidated API writes; custom management forks adding protocols.
Common situations: Partial fleet upgrades: dashboard/management already supports a new protocol, agents lag; scripts creating access policies with an empty/invalid protocol field.
Related errors
- apply firewall rule: %w
- add route rule: %w
- determine destination: %w
- add IP to ipset: %w
- failed to check rule: %w
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/e0cfaa4f5340a386.
Report an issue: GitHub.