tailscale/tailscale · error
invalid Listen addr %q; host part must be empty or IP litera
Error message
invalid Listen addr %q; host part must be empty or IP literal
What it means
resolveListenAddr accepts an empty host or an IP literal only. The host portion of the listen address could not be parsed as an IP, so it is likely a hostname, which tsnet does not resolve for listen addresses.
Source
Thrown at tsnet/tsnet.go:2039
var zero netip.AddrPort
host, portStr, err := net.SplitHostPort(addr)
if err != nil {
return zero, fmt.Errorf("tsnet: %w", err)
}
port, err := net.LookupPort(network, portStr)
if err != nil || port < 0 || port > math.MaxUint16 {
// LookupPort returns an error on out of range values so the bounds
// checks on port should be unnecessary, but harmless. If they do
// match, worst case this error message says "invalid port: <nil>".
return zero, fmt.Errorf("invalid port: %w", err)
}
if host == "" {
return netip.AddrPortFrom(netip.Addr{}, uint16(port)), nil
}
bindHostOrZero, err := netip.ParseAddr(host)
if err != nil {
return zero, fmt.Errorf("invalid Listen addr %q; host part must be empty or IP literal", host)
}
// Normalize unspecified addresses (0.0.0.0, ::) to the zero value,
// equivalent to an empty host, so they match the node's own IPs.
if bindHostOrZero.IsUnspecified() {
return netip.AddrPortFrom(netip.Addr{}, uint16(port)), nil
}
if strings.HasSuffix(network, "4") && !bindHostOrZero.Is4() {
return zero, fmt.Errorf("invalid non-IPv4 addr %v for network %q", host, network)
}
if strings.HasSuffix(network, "6") && !bindHostOrZero.Is6() {
return zero, fmt.Errorf("invalid non-IPv6 addr %v for network %q", host, network)
}
return netip.AddrPortFrom(bindHostOrZero, uint16(port)), nil
}
// ephemeral port range for non-TUN listeners requesting port 0. This range is
// chosen to reduce the probability of collision with host listeners, avoiding
// both the typical ephemeral range, and privilege listener ranges. CollisionsView on GitHub (pinned to 57c3357fdb)
Solutions
- Leave the host empty to listen on all of the node's Tailscale IPs
- Use the node's Tailscale IPv4 or IPv6 literal as the host
Defensive patterns
Strategy: validation
When it happens
Trigger: Thrown at tsnet/tsnet.go:2002 when the library encounters an invalid state.
Common situations: See trigger scenarios.
AI-assisted analysis of tailscale/tailscale@57c3357fdb (2026-08-18).
Data as JSON: /api/errors/d4bdf73bb4bd095a.
Report an issue: GitHub.