{"record":{"id":"2437837110278662","repo":"netbirdio/netbird","slug":"unsupported-protocol-q-must-be-http-https-tcp","errorCode":null,"errorMessage":"unsupported protocol %q: must be http, https, tcp, udp, or tls","messagePattern":"unsupported protocol %q: must be http, https, tcp, udp, or tls","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"client/cmd/expose.go","lineNumber":111,"sourceCode":"// resolveExternalPort returns the effective external port, defaulting to the target port.\nfunc resolveExternalPort(targetPort uint64) uint16 {\n\tif exposeExternalPort != 0 {\n\t\treturn exposeExternalPort\n\t}\n\treturn uint16(targetPort)\n}\n\nfunc validateExposeFlags(cmd *cobra.Command, portStr string) (uint64, error) {\n\tport, err := strconv.ParseUint(portStr, 10, 32)\n\tif err != nil {\n\t\treturn 0, fmt.Errorf(\"invalid port number: %s\", portStr)\n\t}\n\tif port == 0 || port > 65535 {\n\t\treturn 0, fmt.Errorf(\"invalid port number: must be between 1 and 65535\")\n\t}\n\n\tif !isProtocolValid(exposeProtocol) {\n\t\treturn 0, fmt.Errorf(\"unsupported protocol %q: must be http, https, tcp, udp, or tls\", exposeProtocol)\n\t}\n\n\tif isClusterProtocol(exposeProtocol) {\n\t\tif exposePin != \"\" || exposePassword != \"\" || len(exposeUserGroups) > 0 {\n\t\t\treturn 0, fmt.Errorf(\"auth flags (--with-pin, --with-password, --with-user-groups) are not supported for %s protocol\", exposeProtocol)\n\t\t}\n\t} else if cmd.Flags().Changed(\"with-external-port\") {\n\t\treturn 0, fmt.Errorf(\"--with-external-port is not supported for %s protocol\", exposeProtocol)\n\t}\n\n\tif exposePin != \"\" && !pinRegexp.MatchString(exposePin) {\n\t\treturn 0, fmt.Errorf(\"invalid pin: must be exactly 6 digits\")\n\t}\n\n\tif cmd.Flags().Changed(\"with-password\") && exposePassword == \"\" {\n\t\treturn 0, fmt.Errorf(\"password cannot be empty\")\n\t}\n","sourceCodeStart":93,"sourceCodeEnd":129,"githubUrl":"https://github.com/netbirdio/netbird/blob/93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c/client/cmd/expose.go#L93-L129","documentation":"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.","triggerScenarios":"`--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.","commonSituations":"Assuming any L7 protocol name is supported; typos; an exported NB_PROTOCOL from earlier experiments overriding the intended value.","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"],"exampleFix":"# before\nnetbird expose --protocol websocket 8080\n\n# after\nnetbird expose --protocol tcp 8080","handlingStrategy":"validation","validationCode":"valid := map[string]bool{\"http\": true, \"https\": true, \"tcp\": true, \"udp\": true, \"tls\": true}\nif !valid[strings.ToLower(proto)] {\n\tlog.Fatalf(\"unsupported protocol %q; use http, https, tcp, udp, or tls\", proto)\n}","typeGuard":"func isValidExposeProtocol(p string) bool {\n\tswitch strings.ToLower(p) {\n\tcase \"http\", \"https\", \"tcp\", \"udp\", \"tls\":\n\t\treturn true\n\tdefault:\n\t\treturn false\n\t}\n}","tryCatchPattern":null,"preventionTips":["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"],"tags":["cli","validation","protocol","netbird-cli"],"backgroundTag":null,"analyzedSha":"93e97f4bf1ad715072dcb3fb6cdb1763431b5a9c","analyzedAt":"2026-08-16T03:09:19.136Z","schemaVersion":2},"datasetVersion":"2026-08-16T08:17:34.114Z"}