valyala/fasthttp · error

cannot listen on %q: %w

Error message

cannot listen on %q: %w

What it means

After obtaining a bound socket fd and determining the backlog, fdSetup calls unix.Listen(fd, backlog). If the kernel rejects the listen(2) call, the library wraps the syscall error as "cannot listen on %q" with the address. This means the socket was bound but could not be transitioned into a listening state.

Source

Thrown at tcplisten/tcplisten.go:133

	if cfg.FastOpen {
		if err = enableFastOpen(fd); err != nil {
			return err
		}
	}

	if err = unix.Bind(fd, sa); err != nil {
		return fmt.Errorf("cannot bind to %q: %w", addr, err)
	}

	backlog := cfg.Backlog
	if backlog <= 0 {
		if backlog, err = soMaxConn(); err != nil {
			return fmt.Errorf("cannot determine backlog to pass to listen(2): %w", err)
		}
	}
	if err = unix.Listen(fd, backlog); err != nil {
		return fmt.Errorf("cannot listen on %q: %w", addr, err)
	}

	return nil
}

func getSockaddr(network, addr string) (sa unix.Sockaddr, soType int, err error) {
	tcpAddr, err := net.ResolveTCPAddr(network, addr)
	if err != nil {
		return nil, -1, err
	}

	switch network {
	case "tcp4":
		var sa4 unix.SockaddrInet4
		sa4.Port = tcpAddr.Port
		copy(sa4.Addr[:], tcpAddr.IP.To4())
		return &sa4, unix.AF_INET, nil
	case "tcp6":

View on GitHub (pinned to c96f600972)

Solutions

  1. Inspect the wrapped %w error from unix.Listen for the exact errno
  2. Lower cfg.Backlog to a value <= 4096 / kernel somaxconn
  3. Ensure NewListener is called once per socket and the fd is not closed elsewhere
  4. Verify the process has permission to listen on the address (privileges for low ports)

Example fix

// before
cfg := tcplisten.Config{Backlog: 1 << 30} // absurd backlog
ln, err := tcplisten.NewListener(cfg, "tcp", ":8080")
// after
cfg := tcplisten.Config{Backlog: 4096}
ln, err := tcplisten.NewListener(cfg, "tcp", ":8080")
Defensive patterns

Strategy: try-catch

Validate before calling

if cfg.Backlog > 1<<16-1 {
    cfg.Backlog = 1<<16 - 1 // clamp to kernel-safe maximum
}

Try / catch

ln, err := tcplisten.NewListener(cfg, network, addr)
if err != nil && strings.Contains(err.Error(), "cannot listen on") {
    log.Errorf("listen(2) failed on %s: %v", addr, err)
    return fmt.Errorf("listener setup failed for %s: %w", addr, err)
}

Prevention

When it happens

Trigger: NewListener on an address where unix.Listen fails on the already-bound fd — typically when the fd is not a valid listening-capable socket, the socket was closed concurrently, or the backlog exceeds kernel limits (backlog overflow EINVAL on some kernels with values > SOMAXCONN caps).

Common situations: Passing a custom Backlog larger than the kernel accepts; fd misuse in forked/exec'd processes (SO_REUSEPORT inherited sockets); resource exhaustion in the network stack; calling NewListener twice on the same bound fd.

Related errors


AI-assisted analysis of valyala/fasthttp@c96f600972 (2026-08-31). Data as JSON: /api/errors/fe4f66356dc4ead0. Report an issue: GitHub.