netbirdio/netbird · error
auth is not supported for TCP/UDP services
Error message
auth is not supported for TCP/UDP services
What it means
Returned by validateTCPUDPMode when isAuthEnabled() is true: any of password_auth, pin_auth, bearer_auth, or an entry in header_auths with enabled=true triggers it. TCP/UDP modes are byte-stream/datagram passthrough and cannot present an HTTP auth challenge, so the combination is rejected outright rather than silently ignored.
Source
Thrown at management/internals/modules/reverseproxy/service/service.go:925
return nil
}
func (s *Service) validateHTTPMode() error {
if s.Domain == "" {
return errors.New("service domain is required")
}
if s.ListenPort != 0 {
return errors.New("listen_port is not supported for HTTP services")
}
return s.validateHTTPTargets()
}
func (s *Service) validateTCPUDPMode() error {
if s.Domain == "" {
return errors.New("domain is required for TCP/UDP services (used for cluster derivation)")
}
if s.isAuthEnabled() {
return errors.New("auth is not supported for TCP/UDP services")
}
if len(s.Targets) != 1 {
return errors.New("TCP/UDP services must have exactly one target")
}
if s.Mode == ModeUDP && s.Targets[0].ProxyProtocol {
return errors.New("proxy_protocol is not supported for UDP services")
}
return s.validateL4Target(s.Targets[0])
}
func (s *Service) validateTLSMode() error {
if s.Domain == "" {
return errors.New("domain is required for TLS services (used for SNI matching)")
}
if s.isAuthEnabled() {
return errors.New("auth is not supported for TLS services")
}
if s.ListenPort == 0 {View on GitHub (pinned to 93e97f4bf1)
Solutions
- Remove or set enabled=false on all auth blocks (password_auth, pin_auth, bearer_auth, header_auths) for the tcp/udp service.
- If callers genuinely need a login screen, keep the service in http mode where auth is supported.
- Restrict access at the network layer instead: NetBird access groups, ACLs, or access_restrictions (allowed_cidrs).
- Audit the full auth object, not just one sub-block - isAuthEnabled() checks every auth type.
Example fix
// before
{
"mode": "tcp",
"listen_port": 3306,
"auth": { "password_auth": { "enabled": true, "password": "secret" } },
"targets": [...]
}
// after
{
"mode": "tcp",
"listen_port": 3306,
"targets": [...]
} Defensive patterns
Strategy: validation
Validate before calling
func anyAuthEnabled(a AuthConfig) bool {
if (a.PasswordAuth != nil && a.PasswordAuth.Enabled) ||
(a.PinAuth != nil && a.PinAuth.Enabled) ||
(a.BearerAuth != nil && a.BearerAuth.Enabled) {
return true
}
for _, h := range a.HeaderAuths {
if h != nil && h.Enabled {
return true
}
}
return false
}
func checkL4NoAuth(mode string, auth AuthConfig) error {
if (mode == "tcp" || mode == "udp") && anyAuthEnabled(auth) {
return errors.New("strip all auth blocks for tcp/udp services")
}
return nil
} Type guard
func isL4AuthClean(mode string, auth AuthConfig) bool {
if mode != "tcp" && mode != "udp" {
return true
}
return !anyAuthEnabled(auth)
} Try / catch
if err := svc.Validate(); err != nil {
if strings.Contains(err.Error(), "auth is not supported for TCP/UDP") {
return respondBadRequest(errors.New("remove auth or switch to http mode"))
}
return respondBadRequest(err)
} Prevention
- When switching a service's mode in automation, re-derive the whole payload instead of patching one field.
- Remember all four auth types count: password, pin, bearer, header.
- For L4 access control use NetBird groups/ACLs or access_restrictions, never the auth block.
When it happens
Trigger: Creating a tcp/udp service whose payload still carries auth.password_auth.enabled=true, auth.pin_auth, auth.bearer_auth, or auth.header_auths[*].enabled=true; switching a previously HTTP service with basic auth to mode tcp without stripping the auth block.
Common situations: Cloning an HTTP service JSON (which had basic auth) for a new database TCP forward. A UI auth tab left enabled when the mode dropdown changed to TCP. A version upgrade where auth fields on L4 services were previously ignored and are now validated, breaking old automation payloads.
Related errors
- domain is required for TCP/UDP services (used for cluster de
- TCP/UDP services must have exactly one target
- auth is not supported for TLS services
- target_id is required for L4 services
- session_idle_timeout must be positive for L4 services
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/0e9a7af2abe777d7.
Report an issue: GitHub.