netbirdio/netbird · error

invalid address %s

Error message

invalid address %s

What it means

SingleSocketUDPMux.GetConn(ufrag, addr, candidateID) keys muxed connections by ufrag but first validates addr: unless the mux was created over an unspecified address (detected via localAddrsForUnspecified being non-empty), the provided addr must string-equal the bound socket's LocalAddr. This error rejects a request for a connection with a different address than the single socket the mux owns.

Source

Thrown at client/iface/udpmux/mux.go:251

	m.mu.Lock()
	defer m.mu.Unlock()
	if len(m.localAddrsForUnspecified) > 0 {
		return slices.Clone(m.localAddrsForUnspecified)
	}

	return []net.Addr{m.LocalAddr()}
}

// GetConn returns a PacketConn given the connection's ufrag and network address
// creates the connection if an existing one can't be found
func (m *SingleSocketUDPMux) GetConn(ufrag string, addr net.Addr, candidateID string) (net.PacketConn, error) {
	// don't check addr for mux using unspecified address
	m.mu.Lock()
	lenLocalAddrs := len(m.localAddrsForUnspecified)
	m.mu.Unlock()
	if lenLocalAddrs == 0 && m.params.UDPConn.LocalAddr().String() != addr.String() {
		return nil, fmt.Errorf("invalid address %s", addr.String())
	}

	var isIPv6 bool
	if udpAddr, _ := addr.(*net.UDPAddr); udpAddr != nil && udpAddr.IP.To4() == nil {
		isIPv6 = true
	}
	m.mu.Lock()
	defer m.mu.Unlock()

	if m.IsClosed() {
		return nil, io.ErrClosedPipe
	}

	if conn, ok := m.getConn(ufrag, isIPv6); ok {
		return conn, nil
	}

	c := m.createMuxedConn(ufrag, candidateID)

View on GitHub (pinned to 93e97f4bf1)

Solutions

  1. Bind the mux's UDPConn to an unspecified address (0.0.0.0 or [::]) so the strict equality check is skipped
  2. Pass exactly the address reported by the conn's LocalAddr()/GetListenAddresses()
  3. Align the address family of candidates with the bound socket family
  4. Re-create the mux with a correctly bound UDPConn

Example fix

// before: bound to a specific IP
conn, _ := net.ListenUDP("udp4", &net.UDPAddr{IP: net.ParseIP("192.0.2.10"), Port: 3478})
mux, _ := NewSingleSocketUDPMux(Params{UDPConn: conn})
c, err := mux.GetConn(ufrag, raddr, cid) // raddr from another interface -> invalid address

// after: unspecified bind skips the equality check
conn, _ := net.ListenUDP("udp4", &net.UDPAddr{Port: 3478})
mux, _ := NewSingleSocketUDPMux(Params{UDPConn: conn})
c, err := mux.GetConn(ufrag, raddr, cid)
Defensive patterns

Strategy: validation

Validate before calling

local := udpConn.LocalAddr().String()
unspecified := false
if ua, ok := udpConn.LocalAddr().(*net.UDPAddr); ok {
    unspecified = ua.IP.IsUnspecified()
}
if !unspecified && addr.String() != local {
    return fmt.Errorf("skipping GetConn: %s is not the mux bind address %s", addr, local)
}

Prevention

When it happens

Trigger: Creating the mux from a UDPConn bound to a specific interface IP, then calling GetConn with a candidate address from another interface or family (v4 vs v6, LAN IP vs loopback); an ICE candidate arriving whose address differs from the bind address.

Common situations: Bind address pinned to one IP while the peer reaches the host via another address; dual-stack mismatch; tests using 127.0.0.1 against a mux bound to the LAN address.

Related errors


AI-assisted analysis of netbirdio/netbird@93e97f4bf1 (2026-08-16). Data as JSON: /api/errors/8bc91fdbd8a602c8. Report an issue: GitHub.