netbirdio/netbird · warning
unsupported protocol %q: must be http, https, tcp, udp, or t
Error message
unsupported protocol %q: must be http, https, tcp, udp, or tls
What it means
The --protocol flag value is not in the accepted set. isProtocolValid accepts exactly http, https, tcp, udp, tls (case-insensitive); the flag defaults to http. Rejected in validateExposeFlags before the daemon is contacted.
Source
Thrown at client/cmd/expose.go:111
// resolveExternalPort returns the effective external port, defaulting to the target port.
func resolveExternalPort(targetPort uint64) uint16 {
if exposeExternalPort != 0 {
return exposeExternalPort
}
return uint16(targetPort)
}
func validateExposeFlags(cmd *cobra.Command, portStr string) (uint64, error) {
port, err := strconv.ParseUint(portStr, 10, 32)
if err != nil {
return 0, fmt.Errorf("invalid port number: %s", portStr)
}
if port == 0 || port > 65535 {
return 0, fmt.Errorf("invalid port number: must be between 1 and 65535")
}
if !isProtocolValid(exposeProtocol) {
return 0, fmt.Errorf("unsupported protocol %q: must be http, https, tcp, udp, or tls", exposeProtocol)
}
if isClusterProtocol(exposeProtocol) {
if exposePin != "" || exposePassword != "" || len(exposeUserGroups) > 0 {
return 0, fmt.Errorf("auth flags (--with-pin, --with-password, --with-user-groups) are not supported for %s protocol", exposeProtocol)
}
} else if cmd.Flags().Changed("with-external-port") {
return 0, fmt.Errorf("--with-external-port is not supported for %s protocol", exposeProtocol)
}
if exposePin != "" && !pinRegexp.MatchString(exposePin) {
return 0, fmt.Errorf("invalid pin: must be exactly 6 digits")
}
if cmd.Flags().Changed("with-password") && exposePassword == "" {
return 0, fmt.Errorf("password cannot be empty")
}
View on GitHub (pinned to 93e97f4bf1)
Solutions
- Use one of: http, https, tcp, udp, tls (lower or upper case)
- For gRPC, websocket, or other raw stream services, expose as tcp or tls
- Check for a stray NB_PROTOCOL env var: `echo $NB_PROTOCOL` and unset it if wrong
Example fix
# before netbird expose --protocol websocket 8080 # after netbird expose --protocol tcp 8080
Defensive patterns
Strategy: validation
Validate before calling
valid := map[string]bool{"http": true, "https": true, "tcp": true, "udp": true, "tls": true}
if !valid[strings.ToLower(proto)] {
log.Fatalf("unsupported protocol %q; use http, https, tcp, udp, or tls", proto)
} Type guard
func isValidExposeProtocol(p string) bool {
switch strings.ToLower(p) {
case "http", "https", "tcp", "udp", "tls":
return true
default:
return false
}
} Prevention
- Whitelist the protocol before invoking the CLI; only five values are legal
- Expose non-HTTP protocols (gRPC, websocket, SSH) as tcp or tls
- Check that NB_PROTOCOL is unset when relying on the http default
When it happens
Trigger: `--protocol websocket`, `--protocol grpc`, `--protocol httsp` (typo), or `--protocol=` (empty). Also reachable when the NB_PROTOCOL environment variable carries an invalid value, because SetFlagsFromEnvVars maps NB_PROTOCOL onto the flag.
Common situations: Assuming any L7 protocol name is supported; typos; an exported NB_PROTOCOL from earlier experiments overriding the intended value.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- auth flags (--with-pin, --with-password, --with-user-groups)
- invalid protocol: %w
- invalid port number: %s
- invalid port number: must be between 1 and 65535
- --with-external-port is not supported for %s protocol
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/2437837110278662.
Report an issue: GitHub.