{"record":{"id":"417580f69e7a9ecb","repo":"grpc/grpc-go","slug":"error-setting-option-on-socket-v","errorCode":null,"errorMessage":"error setting option on socket: %v","messagePattern":"error setting option on socket: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"internal/syscall/syscall_linux.go","lineNumber":85,"sourceCode":"\treturn uTimeElapsed, sTimeElapsed\n}\n\n// SetTCPUserTimeout sets the TCP user timeout on a connection's socket\nfunc SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {\n\ttcpconn, ok := conn.(*net.TCPConn)\n\tif !ok {\n\t\t// not a TCP connection. exit early\n\t\treturn nil\n\t}\n\trawConn, err := tcpconn.SyscallConn()\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error getting raw connection: %v\", err)\n\t}\n\terr = rawConn.Control(func(fd uintptr) {\n\t\terr = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))\n\t})\n\tif err != nil {\n\t\treturn fmt.Errorf(\"error setting option on socket: %v\", err)\n\t}\n\n\treturn nil\n}\n\n// GetTCPUserTimeout gets the TCP user timeout on a connection's socket\nfunc GetTCPUserTimeout(conn net.Conn) (opt int, err error) {\n\ttcpconn, ok := conn.(*net.TCPConn)\n\tif !ok {\n\t\terr = fmt.Errorf(\"conn is not *net.TCPConn. got %T\", conn)\n\t\treturn\n\t}\n\trawConn, err := tcpconn.SyscallConn()\n\tif err != nil {\n\t\terr = fmt.Errorf(\"error getting raw connection: %v\", err)\n\t\treturn\n\t}\n\terr = rawConn.Control(func(fd uintptr) {","sourceCodeStart":67,"sourceCodeEnd":103,"githubUrl":"https://github.com/grpc/grpc-go/blob/03255a9237b6eb32710f6bc4f2de9a675b99fe36/internal/syscall/syscall_linux.go#L67-L103","documentation":"This error occurs in SetTCPUserTimeout when the rawConn.Control callback or syscall.SetsockoptInt fails to set the TCP_USER_TIMEOUT socket option. This option (Linux-specific) tells the kernel how long to wait for an ACK before aborting the connection. Failure indicates a kernel or socket-level problem.","triggerScenarios":"During transport setup, after obtaining the raw fd, syscall.SetsockoptInt(fd, IPPROTO_TCP, TCP_USER_TIMEOUT, value) returns a non-nil error. This could be an EINVAL from an invalid timeout value, ENOPROTOOPT on kernels that don't support TCP_USER_TIMEOUT, or EBADF if the fd is stale.","commonSituations":"Running on an older Linux kernel (< 2.6.37) that doesn't support TCP_USER_TIMEOUT, running on a non-Linux OS via a compatibility layer that rejects the option, or a race condition where the fd was closed before setsockopt executed.","solutions":["Verify the OS/kernel supports TCP_USER_TIMEOUT (Linux >= 2.6.37).","Check for connection races where the fd is closed before the setsockopt call completes.","If on a minimal container/VM, ensure the kernel is recent enough.","This error is fatal to transport creation — review whether a custom keepalive timeout is necessary and falls back if the kernel doesn't support it."],"exampleFix":"// No direct code fix — this is a kernel/environment capability issue.\n// Verify kernel support:\n//   uname -r  # ensure >= 2.6.37\n//   # check the option exists:\n//   grep TCP_USER_TIMEOUT /usr/include/netinet/tcp.h\n\n// If unsupported, avoid setting keepalive params that trigger SetTCPUserTimeout:\n// Use default keepalive (Time == infinity) or ensure your runtime supports the option.","handlingStrategy":"try-catch","validationCode":"// Check kernel support for TCP_USER_TIMEOUT before relying on it\nfunc supportsTCPUserTimeout() bool {\n    // TCP_USER_TIMEOUT is available on Linux >= 2.6.37\n    if runtime.GOOS != \"linux\" { return false }\n    // Optionally probe with a temporary socket\n    fd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)\n    if err != nil { return false }\n    defer syscall.Close(fd)\n    return syscall.SetsockoptInt(fd, syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, 1000) == nil\n}","typeGuard":null,"tryCatchPattern":"if err := syscall.SetTCPUserTimeout(conn, timeout); err != nil {\n    if strings.Contains(err.Error(), \"setting option on socket\") {\n        // kernel may not support TCP_USER_TIMEOUT\n        // proceed without it; keepalive still works at the gRPC level\n        log.Printf(\"warning: TCP_USER_TIMEOUT unsupported: %v\", err)\n    }\n}","preventionTips":["Verify the deployment environment supports TCP_USER_TIMEOUT (Linux >= 2.6.37).","Test on the target kernel version in CI.","Do not treat missing TCP_USER_TIMEOUT as fatal — gRPC keepalive provides application-level liveness."],"tags":["syscall","tcp","socket","linux","setsockopt","keepalive"],"analyzedSha":"03255a9237b6eb32710f6bc4f2de9a675b99fe36","analyzedAt":"2026-08-07T00:29:34.215Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}