netbirdio/netbird · error
listen_port is required for TLS services
Error message
listen_port is required for TLS services
What it means
Returned by validateTLSMode when a tls service has ListenPort == 0. Unlike HTTP (shared hostname-routed listeners) and unlike tcp/udp (where the port allocation is implied by the mode), a TLS service must declare the dedicated port it listens on so the proxy can accept raw TLS and dispatch by SNI. It is the inverse of error 40, which rejects a listen_port on http services.
Source
Thrown at management/internals/modules/reverseproxy/service/service.go:944
}
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 {
return errors.New("listen_port is required for TLS services")
}
if len(s.Targets) != 1 {
return errors.New("TLS services must have exactly one target")
}
return s.validateL4Target(s.Targets[0])
}
func (s *Service) validateHTTPTargets() error {
for i, target := range s.Targets {
switch target.TargetType {
case TargetTypePeer, TargetTypeHost, TargetTypeDomain:
// Host is normally overwritten by replaceHostByLookup with the
// resolved peer IP / resource address; operator-supplied values
// are honored only when DirectUpstream is set. Validate the
// override here so misconfigured hosts fail fast at API time.
if err := validateDirectUpstreamHost(i, target); err != nil {
return err
}View on GitHub (pinned to 93e97f4bf1)
Solutions
- Set listen_port to the port the proxy should accept TLS on, e.g. 4433 or 853.
- Double-check you set listen_port (service-level listener), not target.port (upstream port).
- If you wanted hostname routing without a dedicated port, use mode http with an https target_protocol instead.
Example fix
// before
{ "mode": "tls", "domain": "db.netbird.example.com",
"targets": [ { "target_id": "peer-a", "port": 5432 } ] }
// after
{ "mode": "tls", "domain": "db.netbird.example.com", "listen_port": 4433,
"targets": [ { "target_id": "peer-a", "port": 5432 } ] } Defensive patterns
Strategy: validation
Validate before calling
func checkTLSListenPort(mode string, listenPort uint16) error {
if mode == "tls" && listenPort == 0 {
return errors.New("listen_port is required for tls services")
}
return nil
} Type guard
func hasTLSListenPort(mode string, listenPort uint16) bool {
return mode != "tls" || listenPort != 0
} Try / catch
if err := svc.Validate(); err != nil {
if strings.Contains(err.Error(), "listen_port is required for TLS") {
return respondBadRequest(errors.New("set an explicit proxy listener port, e.g. 4433"))
}
return respondBadRequest(err)
} Prevention
- Name fields clearly in clients: listener port vs upstream target port.
- Do not assume SNI sharing on 443 - this implementation wants a dedicated listen_port for tls.
- Check port availability on the proxy host before choosing a value.
When it happens
Trigger: Creating a tls service with no listen_port in the payload; an API client that maps its generic 'port' field to the target port but never to listen_port; switching mode from http to tls on a service that legitimately had no listen port.
Common situations: Assuming TLS shares the standard 443 listener via SNI so no port is needed - this implementation requires an explicit dedicated port. Confusion between target.port (upstream) and listen_port (proxy listener). In the peer-expose request the fields are Port and ListenPort, and only ListenPort overrides the listener for L4.
Understand the failure class
- SSL/TLS and certificate errors — how TLS handshakes and certificate validation fail.
Related errors
- listen_port is not supported for HTTP services
- domain is required for TCP/UDP services (used for cluster de
- auth is not supported for TCP/UDP services
- TCP/UDP services must have exactly one target
- domain is required for TLS services (used for SNI matching)
AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16).
Data as JSON: /api/errors/354f815444c0fd98.
Report an issue: GitHub.