valyala/fasthttp · error

cannot enable tcp_defer_accept: %s

Error message

cannot enable tcp_defer_accept: %s

What it means

tcplisten can set TCP_DEFER_ACCEPT on Linux so accept(2) only returns once data arrives. enableDeferAccept applies the setsockopt and wraps any kernel refusal as "cannot enable tcp_defer_accept". It is triggered when the DeferAccept option is enabled in Config and NewListener calls fdSetup.

Source

Thrown at tcplisten/tcplisten_linux.go:21

package tcplisten

import (
	"fmt"
	"os"
	"strconv"
	"strings"

	"golang.org/x/sys/unix"
)

const (
	soReusePort = 0x0F
	tcpFastOpen = 0x17
)

func enableDeferAccept(fd int) error {
	if err := unix.SetsockoptInt(fd, unix.IPPROTO_TCP, unix.TCP_DEFER_ACCEPT, 1); err != nil {
		return fmt.Errorf("cannot enable tcp_defer_accept: %s", err)
	}
	return nil
}

func enableFastOpen(fd int) error {
	if err := unix.SetsockoptInt(fd, unix.SOL_TCP, tcpFastOpen, fastOpenQlen); err != nil {
		return fmt.Errorf("cannot enable tcp_fastopen(qlen=%d): %s", fastOpenQlen, err)
	}
	return nil
}

const fastOpenQlen = 16 * 1024

func soMaxConn() (int, error) {
	data, err := os.ReadFile(soMaxConnFilePath)
	if err != nil {
		// This error may trigger on travis build. Just use SOMAXCONN
		if os.IsNotExist(err) {

View on GitHub (pinned to c96f600972)

Solutions

  1. Set Config.DeferAccept to false if the environment does not support it
  2. Verify kernel support: grep TCP_DEFER_ACCEPT /proc/net/... or check kernel version >= 2.4
  3. Check seccomp/LSM policies allow setsockopt with IPPROTO_TCP
  4. Confirm the runtime is real Linux, not an emulator lacking the option

Example fix

// before
cfg := tcplisten.Config{DeferAccept: true} // fails on restricted kernel
// after
cfg := tcplisten.Config{DeferAccept: isLinuxWithDeferAccept()} // gate the option
ln, err := tcplisten.NewListener(cfg, "tcp", ":8080")
Defensive patterns

Strategy: fallback

Validate before calling

func deferAcceptSupported() bool {
    if runtime.GOOS != "linux" { return false }
    data, err := os.ReadFile("/proc/sys/net/ipv4/tcp_available_congestion_control") // presence check only
    return err == nil && len(data) > 0 // combine with kernel >= 2.4 check
}

Try / catch

cfg := tcplisten.Config{DeferAccept: wantDeferAccept}
ln, err := tcplisten.NewListener(cfg, "tcp", addr)
if err != nil && strings.Contains(err.Error(), "tcp_defer_accept") {
    log.Warn("TCP_DEFER_ACCEPT unsupported; retrying without it")
    cfg.DeferAccept = false
    ln, err = tcplisten.NewListener(cfg, "tcp", addr)
}

Prevention

When it happens

Trigger: NewListener with Config{DeferAccept: true} on Linux where setsockopt(fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, 1) fails — kernel without TCP_DEFER_ACCEPT support, hardened LSM/seccomp blocking the socket option, or an invalid fd.

Common situations: Running in containers with restricted syscalls; exotic kernels or gVisor/sandboxed runtimes lacking TCP_DEFER_ACCEPT; very old kernels.

Related errors


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