probelabs/goreplay · error

err.Error()

Error message

err.Error()

What it means

newVXLANHandler opens a UDP socket on the configured VXLAN address/port via net.ListenUDP. If the OS cannot bind the socket, the underlying error is wrapped with fmt.Errorf(err.Error()), losing the error chain and producing an error identical to the raw Go net error (e.g. 'listen udp 0.0.0.0:4789: bind: address already in use'). It surfaces when activateVxLanSocket is called and the listen fails.

Source

Thrown at internal/capture/vxlan.go:33

	connection    *net.UDPConn
	packetChannel chan gopacket.Packet
	vnis          []int
}

func newVXLANHandler(port int, vnis []int) (*vxlanHandle, error) {
	if port == 0 {
		port = 4789
	}

	addr := net.UDPAddr{
		Port: port,
		IP:   net.ParseIP("0.0.0.0"),
	}

	vxlanHandle := &vxlanHandle{}
	con, err := net.ListenUDP("udp", &addr)
	if err != nil {
		return nil, fmt.Errorf(err.Error())
	}
	vxlanHandle.connection = con
	vxlanHandle.packetChannel = make(chan gopacket.Packet, 1000)
	vxlanHandle.vnis = vnis
	go vxlanHandle.reader()

	return vxlanHandle, nil
}

func (v *vxlanHandle) reader() {
	for {
		inputBytes := make([]byte, VxLanPacketSize)
		length, _, err := v.connection.ReadFromUDP(inputBytes)
		if err != nil {
			if errors.Is(err, net.ErrClosed) {
				return
			}
			continue

View on GitHub (pinned to 251e45abd2)

Solutions

  1. Find the process holding the port (ss -lunp | grep 4789 or lsof -i :4789) and stop it, or change the configured VXLAN port/address.
  2. If two agents are intended, run one per host/network namespace instead of binding the same UDP port twice.
  3. Fix the configured bind address to a valid local IP or 0.0.0.0.
  4. Ensure the process has permission to bind (capabilities NET_RAW/NET_BIND_SERVICE in containers).
  5. Improve the code to wrap with %w: fmt.Errorf("vxlan listen: %w", err) to preserve the chain.

Example fix

// before
return nil, fmt.Errorf(err.Error())
// after
return nil, fmt.Errorf("listen vxlan udp %s: %w", addr.String(), err)
Defensive patterns

Strategy: validation

Validate before calling

func canBindUDP(addr string) error {
	c, err := net.ListenUDP("udp", addr)
	if err != nil { return err }
	return c.Close()
}

Try / catch

h, err := newVXLANHandler(addr, vnis)
if err != nil {
	var oe *net.OpError
	if errors.As(err, &oe) && strings.Contains(oe.Err.Error(), "address already in use") {
		// pick another port or stop the conflicting process
	}
	return err
}

Prevention

When it happens

Trigger: Calling activateVxLanSocket when the UDP port is already bound by another process (or another capture instance), when the address is not assignable to a local interface, or when the process lacks permission (e.g. restricted container without NET_BIND_SERVICE on a privileged port).

Common situations: Running two capture agents on the same host against the same VXLAN port (4789 by default); port already taken by another VXLAN listener; running in a container with a too-restrictive securityContext; typo in host address passed in the config.

Related errors


AI-assisted analysis of probelabs/goreplay@251e45abd2 (2026-09-02). Data as JSON: /api/errors/75d086857d88e51b. Report an issue: GitHub.