juanfont/headscale · error · ErrInvalidProtocolNumber
%w: %q must be a known protocol name or valid protocol numbe
Error message
%w: %q must be a known protocol name or valid protocol number 0-255
What it means
Protocol.validate fell through the known-name list and numeric parsing: the string is neither a recognized protocol name nor a parseable integer (ErrInvalidProtocolNumber). The message reminds the valid range 0-255.
Source
Thrown at hscontrol/policy/v2/types.go:1775
case "", ProtocolNameICMP, ProtocolNameIGMP, ProtocolNameIPv4, ProtocolNameIPInIP,
ProtocolNameTCP, ProtocolNameEGP, ProtocolNameIGP, ProtocolNameUDP, ProtocolNameGRE,
ProtocolNameESP, ProtocolNameAH, ProtocolNameSCTP, ProtocolNameIPv6ICMP, ProtocolNameFC:
return nil
case ProtocolNameWildcard:
// Wildcard "*" is not allowed - Tailscale rejects it
return errUnknownProtocolWildcard
default:
// Try to parse as a numeric protocol number
str := string(*p)
// Check for leading zeros (not allowed by Tailscale)
if str == "0" || (len(str) > 1 && str[0] == '0') {
return fmt.Errorf("%w: %q", ErrProtocolLeadingZero, str)
}
protocolNumber, err := strconv.Atoi(str)
if err != nil {
return fmt.Errorf("%w: %q must be a known protocol name or valid protocol number 0-255", ErrInvalidProtocolNumber, *p)
}
if protocolNumber < 0 || protocolNumber > 255 {
return fmt.Errorf("%w: %d", ErrProtocolOutOfRange, protocolNumber)
}
return nil
}
}
// MarshalJSON implements JSON marshaling for [Protocol].
func (p *Protocol) MarshalJSON() ([]byte, error) {
return json.Marshal(string(*p))
}
// Protocol constants matching the IANA numbers.
const (
ProtocolICMP = 1 // Internet Control MessageView on GitHub (pinned to 565fd254d0)
Solutions
- Use a known lowercase protocol name: tcp, udp, icmp, gre, esp, ah, sctp, etc.
- Or use a plain integer 1-255 without padding
- Trim whitespace and verify casing
Example fix
// before
{"proto": "TCP", "ports": [...]}
// after
{"proto": "tcp", "ports": [...]} Defensive patterns
Strategy: validation
Validate before calling
var knownProtocols = map[string]bool{"tcp": true, "udp": true, "icmp": true, "gre": true, "esp": true, "ah": true, "sctp": true, "egp": true, "igp": true, "ipv6-icmp": true, "fc": true}
func validProtocol(s string) bool {
s = strings.TrimSpace(s)
if knownProtocols[s] { return true }
_, err := strconv.Atoi(s)
return err == nil && validProtocolNumber(s)
} Prevention
- Use lowercase canonical protocol names
- Trim whitespace around values copied from docs
When it happens
Trigger: A proto value like "htcp", "TCP " (trailing space), or any non-numeric unknown word. Note also that wildcard "*" reaches a dedicated earlier error, not this one.
Common situations: Typos in protocol names, casing errors (protocol names must be lowercase), or trailing whitespace from copy-paste.
Related errors
- invalid protocol number
- leading 0 not permitted in protocol number
- protocol number out of range (0-255)
- protocol does not support specific ports
- test protocol must be tcp, udp, sctp, or empty
AI-assisted analysis of juanfont/headscale@565fd254d0 (2026-08-15).
Data as JSON: /api/errors/199d0a5cb9c21e5f.
Report an issue: GitHub.